【发布时间】:2013-11-18 12:20:37
【问题描述】:
所以玩移动语义。
所以我第一次看到这个是这样的:
class String
{
char* data;
int len;
public:
// Normal rule of three applied up here.
void swap(String& rhs) throw()
{
std::swap(data, rhs.data);
std::swap(len, rhs.len);
}
String& operator=(String rhs) // Standard Copy and swap.
{
rhs.swap(*this);
return *this;
}
// New Stuff here.
// Move constructor
String(String&& cpy) throw() // ignore old throw construct for now.
: data(NULL)
, len(0)
{
cpy.swap(*this);
}
String& operator=(String&& rhs) throw()
{
rhs.swap(*this);
return *this;
}
};
看着这个。我认为根据 Move 赋值定义 Move 构造函数可能是值得的。它具有很好的对称性,我喜欢它,因为它看起来也很干(并且喜欢复制和交换)。
所以我将移动构造函数重写为:
String(String&& cpy) throw()
: data(NULL)
, len(0)
{
operator=(std::move(cpy));
}
但这会产生歧义错误:
String.cpp:45:9: error: call to member function 'operator=' is ambiguous
operator=(std::move(rhs));
^~~~~~~~~
String.cpp:32:13: note: candidate function
String& operator=(String rhs)
^
String.cpp:49:13: note: candidate function
String& operator=(String&& rhs) throw()
^
1 error generated.
由于我在传递参数时使用了std::move(),因此我希望它绑定到移动赋值运算符。我做错了什么?
【问题讨论】:
-
不过,使用尚不存在的对象的赋值运算符并不卫生。
-
throw()已弃用,取而代之的是noexceptbtw -
我的语义可能混淆了,但
String&&不应该是右值吗?所以调用std::move会尝试将其转换为一个xvalue。你不应该只能打电话给operator=(std::forward(cpy))吗? -
你提到了三法则。这是否意味着您在别处定义了
String::~String()和String::String(const String &input)?这给了我们三分之二,你有你的副本和交换String& String::operator=(...)? -
operator=(String& )和operator=(String&& )可以通过右值参考与左值参考来消除歧义;但不是operator=(String )与operator=(String&& )。
标签: c++ c++11 move-semantics