C++移动语义

3

I have this example:

Widget* makeWidget(int a, int b) {
if (a > b) {
    return new Widget(a);   
}
else {
    return new  Widget(b);  
 }
}

这不就相当于移动返回值吗,因为你只是传递了引用而不是副本?那我为什么要结束移动构造函数/赋值运算符呢?

问候


为什么不这样写:Widget* makeWidget(int a, int b) { return new Widget(a > b ? a : b); } 在C++中,?:运算符甚至可以处理引用。也就是说,我甚至使用它来进行构造函数的条件调用(本身)以初始化实例。 - Scheff's Cat
1
@Scheff 绝对与问题无关。这只是一个明显的例子。 - Bartek Banachewicz
如果提问者没有考虑到(原始)指针赋值并不意味着任何移动语义,他可能也错过了其他(甚至更简单的)机会... - Scheff's Cat
1
还有相关内容 - Bartek Banachewicz
2个回答

1

为什么我需要定义移动构造函数/赋值运算符?

在你的函数中:

Widget* makeWidget(int a, int b);

你正在返回一个Widget*(即Widget的指针),这里并没有进行任何对象的移动。
“将返回值移动”和“传递引用而不是副本”是一样的吗? 从语义上讲,这并不相同,因为通过移动,您总是返回一个对象。 通过移动实际上不是复制,而是将数据从“移动源”对象(即被移动的对象)移动到“移动目标”对象(即通过“移动构造函数”或“移动赋值运算符”构建或分配的对象)。

1
@GillBates 一个原始指针是不能被移动的(更确切地说,移动原始指针和复制它没有什么不同)。 - Walter
@Walter 嗯,这没有任何好处,但我只是注意到它,以使 OP 意识到 return 语句的语义。你说得对,它在这里没有用处。 - Hatted Rooster

1

这取决于你与什么进行比较。如果你将返回类型替换为unique_ptr<Widget>,你需要使用移动构造函数来实现清晰的所有权语义。

与普通的Widget返回相比,如果你这样做,你还可以实现非空性。

在你的情况下,没有进行任何移动,但你也没有任何好处。你返回的东西可能为空,没有所有权规定。没有移动构造函数,你要么这样做,要么被迫复制以保持正确的语义和保证。移动构造函数允许你拥有这个蛋糕,也能吃掉它。


1
虽然在这种情况下,通过std::move()返回一个unique_ptr<Widget>可能会抑制RVO。 - Walter
@Walter 通常在返回语句中不需要使用::std::move(),因为当一个值被返回时,自动进行到右值的转换。 - Ken Wayne VanderLinde

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接