Wal*_*ter 6 c++ constructor move-semantics c++11
我有一些问题,了解何时以及是否调用移动构造函数或移动赋值运算符,特别是在具有常量数据成员的类的上下文中.考虑上课
template<typename T> class A {
const*T const P ; // constant data member
explicit A(const*T p) : P(p) { std::cerr<<" ctor: P="<<P<<'\n'; }
void test() const { std::cerr" test: P="<<P<<'\n'; }
// move and copy constructors and assignment operators here
};
Run Code Online (Sandbox Code Playgroud)
和测试程序
class B {
int X[100];
A<B> get_a() const { return A<B>(this); }
};
int main() {
B b;
A<B> a = b.get_a(); // which operator/ctor is used for '=' here?
a.test();
}
Run Code Online (Sandbox Code Playgroud)
那么编译的结果会有所不同,具体取决于为类中的移动构造函数和移动赋值运算符提供的定义A<>,还有编译器.
1在类中没有任何进一步的声明A<>(如上所述),g ++(4.7.0)和icpc(13.0.1)编译正确(带选项-std=c++11)并产生预期的输出
ctor: P=0x7fffffffd480
test: P=0x7fffffffd480
Run Code Online (Sandbox Code Playgroud)
2如果我宣布
A&A::operator=(A&&) = delete;
A&A::operator=(const A&) = delete;
Run Code Online (Sandbox Code Playgroud)
(鉴于必须初始化初始化的常量数据成员,这似乎是明智的),但是不提供任何进一步的ctor,编译失败了g ++但是没关系icpc.如果另外我定义了(或两者)
A::A(A&&) = default;
A::A(const A&) = default;
Run Code Online (Sandbox Code Playgroud)
两个编译器都很高兴.但是,g ++对这种组合并不满意
A::A(A&&) = delete;
A::A(const A&) = default;
Run Code Online (Sandbox Code Playgroud)
而icpc很高兴.
3如果我和2中的游戏相同,除了A::A(A&&) = default;被替换为
A::A(A&&a) : P(a.P) { std::cerr<<" move ctor: P="<<P<<'\n'; } // never called?
Run Code Online (Sandbox Code Playgroud)
(和等效的A::A(const A&)),结果完全相同,特别是没有从这些显式移动和复制ctors生成输出.
那么,哪些运算符用于=在main()?(为什么在上一次测试中没有产生输出?)
为什么这里允许这个操作,因为它A<>有一个常量数据成员(如果我用这个成员替换成员const*T const P;,结果是相同的const T&R)?
最后,在g ++和icpc的不同行为的情况下,如果有的话,这是正确的吗?
A<B> a = b.get_a();
Run Code Online (Sandbox Code Playgroud)
不是赋值,而是a右值的初始化。如果出现以下情况,此语法在 C++0x 下应该会失败
explicit,复制赋值运算符的声明或删除不应产生任何影响。
更正:与复制构造函数(即使提供了用户定义的复制赋值运算符也会合成)不同,如果定义了用户定义的移动赋值,编译器不会合成移动构造函数。因此,上面的列表应该修改4(我现在已经完成了)。
因此,在我看来,
| 归档时间: |
|
| 查看次数: |
705 次 |
| 最近记录: |