【发布时间】:2012-01-16 10:39:11
【问题描述】:
这是一个通用的编程问题。我正在学习 C++,我了解到任何 const 变量,即:const int i 或 int *const ptr,都必须立即初始化。
这也是地址引用必须立即初始化的根本原因,因为地址是const。
但我找不到必须这样做的原因/为什么要强制执行此规则。
谁能帮我解释一下?
【问题讨论】:
标签: c++ reference initialization constants
这是一个通用的编程问题。我正在学习 C++,我了解到任何 const 变量,即:const int i 或 int *const ptr,都必须立即初始化。
这也是地址引用必须立即初始化的根本原因,因为地址是const。
但我找不到必须这样做的原因/为什么要强制执行此规则。
谁能帮我解释一下?
【问题讨论】:
标签: c++ reference initialization constants
当一个变量被声明为 const 时,这意味着该变量是只读的,并且不能被改变。所以为了使一个变量只读,它应该在它被声明的时候被初始化。
为了更好地理解变量,请查看以下程序
每个进程基本上由进程运行时可以访问的 4 个地址空间部分组成
文本 - 这部分包含要执行的实际 m/c 指令。在许多操作系统上,这被设置为只读,因此进程无法修改其指令。这允许程序的多个实例共享文本的单个副本。
数据 - 这部分包含程序的数据部分。又分为
1) 初始化只读数据 - 这包含由程序初始化的数据元素,它们在进程执行期间是只读的。
2) Initialized Read Write Data - 这包含由程序初始化并在流程执行过程中被修改的数据元素。
3) 未初始化的数据 - 这包含程序未初始化的元素,并且在进程执行之前设置为 0。这些也可以修改并称为 BSS(块开始符号)。这些元素的好处是,系统不必在程序文件中为这个区域分配空间,因为它在进程开始执行之前被操作系统初始化为0。
堆栈 - 这部分用于局部变量,堆栈帧
堆 - 这部分包含动态分配的内存
int abc = 1; ----> Initialized Read-Write Data
char *str; ----> BSS
const int i = 10; -----> Initialized Read-Only Data
main()
{
int ii,a=1,b=2,c; -----> Local Variables on
Stack
char *ptr;
ptr = malloc(4); ------> Allocated Memory in Heap
c= a+b; ------> Text
}
数据,存储数据文本,存储代码
链接器生成的文件有 3 个(主要?)段/部分。 text - 程序文本(显然是 const char 数组。也许是其他 'const' 数组,因为无论如何都无法更改)。我不是 100% 确定数组部分,也许有人会纠正我。
data - 初始化的全局数据。见下面的例子。 bss - 未初始化的全局数据。下面是一些例子
int x = 1; /* goes into data */
int y; /* goes into bss */
const int z = 1;/* goes into text */
这个,我们已经看到进入“文本”,因为无论如何都无法更改,但可以受到保护
【讨论】:
因为您无法在以后对其进行初始化或赋值。
const int size; //no initialization (error)
size = 100; //error - you cannot assign a const variable.
现在,如果一个变量既没有任何有意义的值,也因为它是一个 const 变量,你以后也不允许使它具有值,那么这样一个变量的意义何在?完全没用。
但是,这仅适用于内置和 POD 类型:
struct A{}; //POD type
struct B{ B(){} }; //Non POD type because it has user-defined constructor!
const int i; //error - built-in type
const A a; //error - POD type
const B b; //ok - Non POD type
//likewise
const std::string s; //ok - std::string is a non-POD
const std::vector<std::string> v; //ok - std::vector is a non-POD
实际上一个非 POD 类型不能保持未初始化,因为会调用默认构造函数,并且对象会被初始化。
现在考虑这个结构,
struct C
{
const int i;
C() {}
};
C 绝对是非 POD 类型,因为它有用户定义的构造函数。另请注意,在构造函数中,它不会初始化 i,即int,声明为const。因为这个未初始化的const i,下面会报错:
const C c; //error -
有人可能会认为错误是因为上面声明的变量c 中的const。但这是短视的,不是真的。即使删除const,也会报错:
C c; //error - same error
错误是因为C::i 声明为const 但尚未初始化。
该分析还表明,内置类型不会自动初始化,即使它们是非 POD 类型的成员。非 POD 类类型也是如此。
内置类型(和 POD 类型)的 default 初始化语法如下:
struct C
{
const int i;
C() : i() {} //note the syntax - it is called member-initialization list
};
现在这是允许的:
C x; //ok
const C y; //ok
至于什么是结构/类 POD,请参阅此主题:
【讨论】:
int i 不会初始化为 0(如果它是局部变量),规范不保证这一点。但是,如果您在命名空间级别写入int i,那么它会静态地 初始化为0。但是当您将其设为const 变量时,您会报错。这就是语言规范定义行为的方式。
不允许在程序中为 const 变量赋值,因为那样你可能会改变它的值,这显然是错误的!!!!
因此,您需要初始化它们..
希望对你有帮助
【讨论】:
因为如果您以后可以分配给它们,它们就不会是“const”。
【讨论】:
const 变量的重要属性是它只能被分配一次。因此,如果它可以在分配发生后进行分配,那么它就不会是const。但没有什么要求在声明时进行分配。所以我认为 OP 要问的是,为什么初始分配必须作为声明的一部分发生?
const 变量不能永远被赋值。并回答您的观点;你把声明和定义混为一谈了。
final 变量。但只有一次。