当前位置:  开发笔记 > 编程语言 > 正文

"const static"在C和C++中意味着什么?

如何解决《"conststatic"在C和C++中意味着什么?》经验,为你挑选了5个好方法。

很多人给出了基本答案,但没有人指出,在C++中const默认staticnamespace水平(有的给出了错误信息).请参阅C++ 98标准第3.5.3节.

首先是一些背景:

翻译单元:预处理器(递归地)之后的源文件包括其所有包含文件.

静态链接:符号仅在其翻译单元中可用.

外部链接:其他翻译单元可以使用符号.

namespace水平

这包括全局命名空间aka全局变量.

static const int sci = 0; // sci is explicitly static
const int ci = 1;         // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3;        // ei is explicitly extern
int i = 4;                // i is implicitly extern
static int si = 5;        // si is explicitly static

在功能级别

static表示在函数调用之间保持该值.
函数static变量的语义类似于全局变量,因为它们驻留在程序的数据段(而不是堆栈或堆)中,有关变量生命周期的更多详细信息,请参阅此问题static.

class水平

static表示该值在类的所有实例之间共享,并且const意味着它不会更改.



1> Motti..:

很多人给出了基本答案,但没有人指出,在C++中const默认staticnamespace水平(有的给出了错误信息).请参阅C++ 98标准第3.5.3节.

首先是一些背景:

翻译单元:预处理器(递归地)之后的源文件包括其所有包含文件.

静态链接:符号仅在其翻译单元中可用.

外部链接:其他翻译单元可以使用符号.

namespace水平

这包括全局命名空间aka全局变量.

static const int sci = 0; // sci is explicitly static
const int ci = 1;         // ci is implicitly static
extern const int eci = 2; // eci is explicitly extern
extern int ei = 3;        // ei is explicitly extern
int i = 4;                // i is implicitly extern
static int si = 5;        // si is explicitly static

在功能级别

static表示在函数调用之间保持该值.
函数static变量的语义类似于全局变量,因为它们驻留在程序的数据段(而不是堆栈或堆)中,有关变量生命周期的更多详细信息,请参阅此问题static.

class水平

static表示该值在类的所有实例之间共享,并且const意味着它不会更改.


在函数级别:static不是const还原,它们可以表现不同`const int*foo(int x){const int b = x; return&b};`vs`const int*foo(int x){static const int b = x; return&b};`

2> Chris Arguin..:

它在C和C++中都有用.

正如您所猜测的那样,该static部分将其范围限制在该编译单元.它还提供静态初始化.const只是告诉编译器不要让任何人修改它.根据体系结构,此变量可以放在数据段或bss段中,也可以在内存中标记为只读.

这就是C如何处理这些变量(或C++如何处理命名空间变量).在C++中,标记的成员static由给定类的所有实例共享.它是否为私有不会影响一个变量由多个实例共享的事实.如果const有任何代码会尝试修改它,那么就会在那里发出警告.

如果它是严格私有的,那么该类的每个实例都将获得自己的版本(尽管优化器).



3> Richard Cord..:

这行代码实际上可以出现在几个不同的上下文中,并且尽管它的行为大致相同,但存在小的差异.

命名空间范围
// foo.h
static const int i = 0;

' i'将在包含标题的每个翻译单元中显示.但是,除非您实际使用对象的地址(例如.' &i'),否则我很确定编译器会将' i'简单地视为类型安全0.如果两个以上的翻译单元采用' &i',则每个翻译单元的地址将不同.

// foo.cc
static const int i = 0;

' i'具有内部联系,因此不能从该翻译单元外部引用.但是,除非您使用其地址,否则它很可能被视为类型安全0.

值得指出的一点是,以下声明:

const int i1 = 0;

完全相同一样static const int i = 0.声明为const和未显式声明的名称空间中的变量extern是隐式静态的.如果您考虑这一点,C++委员会的目的是允许const在头文件中声明变量而不总是需要static关键字以避免破坏ODR.

类范围
class A {
public:
  static const int i = 0;
};

在上面的示例中,标准明确指定i如果不需要其地址则不需要定义' '.换句话说,如果您只使用' i'作为类型安全0,那么编译器将不会定义它.类和命名空间版本之间的一个区别是,' i'(如果在两个以上的翻译单元中使用)的地址对于类成员将是相同的.在使用地址的地方,您必须有一个定义:

// a.h
class A {
public:
  static const int i = 0;
};

// a.cc
#include "a.h"
const int A::i;            // Definition so that we can take the address


+1表示静态const与命名空间范围中的const相同.
@Mikhail:你说的没错.假设标头可以包含在多个TU中,因此单独讨论它是有用的.

4> Ferruccio..:

这是一个小空间优化.

当你说

const int foo = 42;

您没有定义常量,而是创建只读变量.编译器足够智能,只要看到foo就会使用42,但它也会为初始化数据区域分配空间.这样做是因为,如所定义的,foo具有外部链接.另一个编译单位可以说:

extern const int foo;

获取其价值的访问权限.这不是一个好习惯,因为编译单元不知道foo的价值是什么.它只知道它是一个const int,并且必须在使用它时从内存重新加载它.

现在,通过声明它是静态的:

static const int foo = 42;

编译器可以进行通常的优化,但它也可以说"嘿,这个编译单元之外的任何人都看不到foo,我知道它总是42,所以不需要为它分配任何空间."

我还应该注意,在C++中,防止名称转义当前编译单元的首选方法是使用匿名命名空间:

namespace {
    const int foo = 42; // same as static definition above
}



5> Kevin..:

它缺少'int'.它应该是:

const static int foo = 42;

在C和C++中,它声明了一个整数常量,其本地文件范围为42.

为什么42?如果你还不知道(很难相信你不知道),那就是对生命,宇宙和万物回答.

推荐阅读
pan2502851807
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有