Wil*_*ley 14 c++ clang default-copy-constructor c++11
根据与c ++ 0x相关的N2628,非静态数据成员初始化器可以被显式定义的构造函数覆盖,但它似乎对隐式定义的复制构造函数略显模糊.
特别是,我注意到使用Apple clang 3.0版时,行为会根据结构(或类)是否为POD而有所不同.
以下程序返回输出"1",表示复制构造函数忽略右侧,而是替换新的非静态数据成员初始值设定项(在此示例中,X :: a的布尔值为true) ).
#include <iostream>
#include <string>
struct X
{
std::string string1;
bool a = true;
};
int main(int argc, char *argv[])
{
X x;
x.a = false;
X y(x);
std::cout << y.a << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是,令人困惑的是,如果你注释掉string1:
// std::string string1;
Run Code Online (Sandbox Code Playgroud)
然后行为按照我的预期工作(输出为"0"),大概是因为没有隐式生成的复制构造函数,因此复制了数据.
C++ 0x规范是否真的建议允许隐式定义的拷贝构造函数不复制右侧的内容?这不是那么有用和不直观吗?我发现非静态成员初始化程序功能非常方便,但如果这是正确的行为,那么由于其棘手和不直观的行为,我将明确地避免使用该功能.
请告诉我,我错了?
更新:此错误已在Clang源存储库中修复.见此修订版.
更新:此错误在Apple clang 3.1版(标签/ Apple/clang-318.0.45)中出现(基于LLVM 3.1svn).这个版本的clang是作为Lion的Xcode 4.3的一部分发布的.
seh*_*ehe 10
毕竟它并不是阴影,请参阅标准摘要的突出部分:
关于默认复制/移动构造函数(第12.8节)的部分有点过于冗长而无法引用它的全部内容.低位是具有初始值设定项的非静态成员字段仍然只是由默认的复制/移动构造函数复制
§12.8:
-6.非联合类X的隐式定义的复制/移动构造函数执行其基础和成员的成员复制/移动.
[ Note: brace-or-equal-initializers of non-static data members are ignored. See also the example in 12.6.2. —end note ]初始化顺序与用户定义构造函数中基数和成员的初始化顺序相同(见12.6.2).设x是构造函数的参数,或者对于移动构造函数,x是引用参数的xvalue.以适合其类型的方式复制/移动每个基本或非静态数据成员:
- 如果成员是一个数组,则使用x的相应子对象直接初始化每个元素;
- 如果成员m具有右值引用类型T &&,则使用static_cast(xm)进行直接初始化;
- 否则,用x的相应基数或成员直接初始化基数或成员.
虚拟基类子对象只能由隐式定义的复制/移动构造函数初始化一次
这是提到的样本:
Run Code Online (Sandbox Code Playgroud)struct A { int i = /* some integer expression with side effects */; A(int arg) : i(arg) { } // ... };A(int)构造函数将简单地将i初始化为arg的值,并且不会发生i的brace-or-equalinitializer中的副作用.
—end example ]
为完整起见,默认默认构造函数的相应部分:
§12.1
-6.当使用odr-used(3.2)创建其类类型(1.8)的对象或在第一次声明后显式默认为默认构造函数时,默认构造函数是默认的并且未定义为已删除.
隐式定义的默认构造函数执行该类的初始化集,该初始化集将由该用户编写的默认构造函数执行,该类没有ctor-initializer(12.6.2)和空复合语句.如果该用户编写的默认构造函数不正确,则程序格式错误.
如果该用户编写的默认构造函数满足constexpr构造函数(7.1.5)的要求,则隐式定义的默认构造函数为constexpr.在隐式定义类的默认默认构造函数之前,应隐式定义其基类及其非静态数据成员的所有非用户提供的默认构造函数.[注意:隐式声明的默认构造函数具有异常规范(15.4).
显式默认定义可能具有隐式异常规范,请参见8.4.—end note ]
| 归档时间: |
|
| 查看次数: |
3621 次 |
| 最近记录: |