繁体   English   中英

移动构造函数应该采用const还是非const rvalue引用?

[英]Should a move constructor take a const or non-const rvalue reference?

在一些地方,我已经看到了复制和移动构造函数的推荐签名,如下所示:

struct T
{
    T();
    T(const T& other);
    T(T&& other);
};

复制构造函数采用const引用,移动构造函数采用非const rvalue引用。

据我所知,这使我无法在从函数返回const对象时利用移动语义,例如下面的情况:

T generate_t()
{
    const T t;
    return t;
}

使用VC11 Beta对此进行测试,调用T的复制构造函数,而不是移动构造函数。 甚至使用return std::move(t); 复制构造函数仍然被调用。

我可以看到这是有道理的,因为t是const所以不应该绑定到T&& 在移动构造函数签名中使用const T&&工作正常,并且有意义,但是你有问题,因为other是const,如果需要将它们排除在外,你不能将其成员归零 - 它只会在所有成员是标量或具有正确签名的移动构造函数。

它看起来像,以确保移动构造函数在一般情况下已经作出的唯一途径t摆在首位非const,但我不喜欢这样做- consting东西是好的形式,我不希望T的客户知道他们不得不反对这种形式以提高性能。

所以,我想我的问题是双重的; 首先,移动构造函数应该采用const还是非const rvalue引用? 第二:我在这种推理中是对的吗? 我应该停止返回const的东西?

这应该是一个非const右值引用。

如果将对象放在只读内存中,则无法从中窃取资源,即使其正式生命周期即将结束。 允许在C ++中以const创建的对象存在于只读内存中(使用const_cast尝试更改它们会导致未定义的行为)。

移动构造函数通常应该采用非const引用。

如果可以从const对象移动,通常意味着复制对象与从其“移动”对象一样有效。 此时,拥有移动构造函数通常没有任何好处。

你也是正确的,如果你有一个你可能想要移动的变量,那么它将需要是非const的。

据我所知,这就是Scott Meyers改变了他对C ++ 11函数中返回类类型对象的建议的原因。 通过const限定值返回对象确实可以防止无意中修改临时对象,但它也会禁止从返回值移动。

移动构造函数应该采用const还是非const rvalue引用?

它应该采用非const rvalue引用 rvalue引用首先在const表单中没有意义,因为你想要修改它们(在某种程度上,你想要“移动”它们,你想要自己的内部)。

此外,它们被设计为在没有 const的情况下使用,我相信const rvalue参考的唯一用途是Scott Meyers在本次演讲中提到的非常神秘的东西(从时间42:20到44:47)。

我在这种推理中是对的吗? 我应该停止返回const的东西?

我认为这是一个太普遍的问题。 在这种情况下,我认为值得一提的是, std::forward功能将保留rvalue-ness和lvalue-ness以及const-ness,并且它还可以避免创建临时函数,因为正常函数会返回任何事情都传递给它。

这种返回也会导致右值引用被“损坏”到左值引用中,并且通常不需要它,因此,使用上述功能完美转发可以解决问题。

话虽这么说,我建议你只看一下我发布链接的话题。

除了在其他答案中所说的内容之外,有时还有移动构造函数或函数接受const T&& 例如,如果将按值返回const对象的函数的结果传递给构造函数,则会调用T(const T&)而不是T(T&&) ,如下所示(参见下面的函数g )。

这是删除接受const T&& for std::refstd::cref而不是接受T&&重载的原因。

具体而言,重载解析期间的优先顺序如下:

struct s {};

void f (      s&);  // #1
void f (const s&);  // #2
void f (      s&&); // #3
void f (const s&&); // #4

const s g ();
s x;
const s cx;

f (s ()); // rvalue        #3, #4, #2
f (g ()); // const rvalue  #4, #2
f (x);    // lvalue        #1, #2
f (cx);   // const lvalue  #2

有关详细信息,请参阅此文章

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM