我很好奇为什么可以在构造函数中修改const成员。
初始化中是否有任何标准规则会覆盖" const-ness"会员?
struct Bar {
const int b = 5; // default member initialization
Bar(int c):b(c) {}
};
Bar *b = new Bar(2); // Problem: Bar::b is modified to 2
// was expecting it to be an error
有什么想法吗?
答案 0 :(得分:66)
这不是修改(或分配),而是initialization。 e.g。
struct Bar {
const int b = 5; // initialization (via default member initializer)
Bar(int c)
:b(c) // initialization (via member initializer list)
{
b = c; // assignment; which is not allowed
}
};
const
数据成员无法修改或分配,但可以(并且需要)通过成员初始化列表或默认成员初始化程序进行初始化。
如果在同一数据成员上提供了默认成员初始值设定项和成员初始值设定项,则将忽略默认成员初始值设定项。这就是为b->b
初始化值2
。
如果成员具有默认成员初始值设定项并且也出现在构造函数的成员初始化列表中,则忽略默认成员初始值设定项。
另一方面,默认成员初始值设定项仅在成员初始值设定项列表中未指定数据成员时生效。 e.g。
struct Bar {
const int b = 5; // default member initialization
Bar(int c):b(c) {} // b is initialized with c
Bar() {} // b is initialized with 5
};
答案 1 :(得分:16)
添加到songyuanyao的好答案,如果你想要一个无法在构造函数中初始化的const
数据成员,你可以成为成员static
:
struct Bar {
static const int b = 5; // static member initialization
Bar(int c)
:b(c) // Error: static data member can only be initialized at its definition
{
b = c; // Error: b is read-only
}
};
在C ++ 17中,您可以通过将其inline
:
struct Bar {
inline static const int b = 5; // static member initialization
Bar(int c)
:b(c) // Error: static data member can only be initialized at its definition
{
b = c; // Error: b is read-only
}
};
这样您就不会遇到ODR问题。
答案 2 :(得分:2)
当你这样做时:
struct Bar {
const int b = 5; // default member initialization
...
};
您告诉编译器使用默认构造函数执行此操作:
...
Bar() : b(5)
{}
...
无论您是否提供了默认构造函数。当您提供默认构造函数和初始分配时,您将覆盖编译器的默认分配代码(即b(5)
)。
当您有多个构造函数时,声明中的默认初始化/赋值很有用,您可能会也可能不会在所有构造函数中分配const成员:
...
Bar() = default; // b=5
Bar(int x) : b(x) // b=x
Bar(double y) : /*other init, but not b*/ // b=5
...