这涉及到C++问题的解决http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1402 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1402。概括:
template<typename T>
struct wrap
{
wrap() = default;
wrap(wrap&&) = default;
wrap(const wrap&) = default;
T t;
};
struct S {
S(){}
S(const S&){}
S(S&&){}
};
typedef wrap<const S> W;
// Error, defaulted move constructor of "wrap<const S>" is deleted!
W get() { return W(); }
(问题是,即使编译器可以简单地使用“S”的复制构造函数,就像用户显式编写“wrap”的移动构造函数时一样,我们也会收到此代码片段的错误。该问题已解决在重载决策期间忽略已删除的移动构造函数(和赋值运算符),因此根据需要使用上面的复制构造函数。)
当决议已起草,提出以下意见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3667.html关于该决议:
相对于复制,隐式/默认移动操作没有其他限制。这意味着虚拟基中的移动赋值是危险的(编译器可能应该警告)[...]但我们在 Batavia 决定不保留所有 C++03 代码以防止隐式移动操作,我认为该分辨率提供了显着的性能优势。
有人可以描述一下虚拟基地移动分配操作员的担忧是什么吗?
考虑:
#include <iostream>
struct A
{
A() = default;
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) {std::cout << "operator=(const A&)\n"; return *this;}
A& operator=(A&&) {std::cout << "operator=(A&&)\n"; return *this;}
};
struct B
: virtual public A
{
};
struct C
: virtual public A
{
};
struct D
: public B,
public C
{
};
int
main()
{
D d1, d2;
d1 = std::move(d2);
}
我相信这个程序应该输出:
operator=(A&&)
operator=(A&&)
对我来说它实际上输出:
operator=(const A&)
operator=(const A&)
但我认为这只是一个 clang bug(用 -std=c++1y 编译)。如果我对输出应该是什么是正确的,那么危险就是移动赋值运算符被调用两次。这对于复制赋值运算符是无害的(尽管可能很昂贵),但对于移动赋值运算符则不然。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)