方法冗余移动调用的移动语义
Move semantic for method redundant move call
说我有这个类
struct Test {
std::string a;
void setA(std::string&& input) {
a = input;
input = "";
}
}
在这里,我将input
的内容移动到a
,然后使input
处于安全可销毁状态。这是移动语义的经典用法,在这里我可以避免复制。
现在说我有这个类
struct Test {
std::string a;
void setA(std::string&& input) {
DoSomeWork(input);
}
void DoSomeWork(std::string&& other) { /* ... */}
}
这仍然正确吗?还是应该使用DoSomeWork(std::move(input));
?我不知道在这种情况下是否需要搬家。
注意在情况1中,我收到一个右值引用作为输入,并使用经典方法。
void setA(std::string&& input) {
a = input; //input is an rvalue referece and I "transfer" its content into a
input = ""; //maybe useless but in some books (including c++ primer) I've seen that it's good practice to "reset" the moved-from object and leave it in a destructable state!
我理解。我不能理解的是:
void setA(std::string&& input) {
//recall that DoSomeWork accepts a std::string&&
DoSomeWork(input);
}
这里,如果我想将input
传递给函数并移动它,我不知道是否需要std::move
。我已经有一个右值参考,所以移动过程是自动的吗?或者需要std::move
呼叫?
这里我将
input
的内容移动到a
中
否。您正在将input
的内容复制到a
。
您可能会混淆类型和值类别。作为一个命名参数,input
是一个左值;给定a = input;
,将调用复制分配运算符,但不调用移动分配运算符。
,然后我将
input
置于安全可销毁状态。
这是多余的,工作应该留给std::string
的移动赋值运算符。
是的,您应该使用std::move
将input
转换为右值,例如
void setA(std::string&& input) {
a = std::move(input); // input is move assigned to a, and left with undetermined but valid state
}
和
void setA(std::string&& input) {
DoSomeWork(std::move(input));
}
在函数签名中
void setA(std::string&& input) { /* ... */ }
变量input
绑定到一个右值,但它本身是一个左值。当你想从中移动构造另一个对象时,你需要事先将其强制转换为一个右值:
void setA(std::string&& input) {
a = std::move(input);
}
请注意,现在没有必要将input
设置为空字符串。你根本不应该再碰这个变量了。当您将input
传递给其他函数时,同样的推理也是正确的:
void setA(std::string&& input) {
/* Cast to rvalue necessary to preserve "rvalue-ness" of the argument: */
DoSomeWork(std::move(input));
}
在这里,我将输入的内容移动到a中,然后使输入处于安全的可销毁状态。这是移动语义的经典用法,在这里我可以避免复制。
不,你不是;即副本。除非在命名的&&
上显式使用std::move
,否则它始终是副本。
此外,当您正确地执行移动时,将前一个对象置于"安全可销毁状态"不是您的责任;这是move构造函数/赋值操作符的职责。
这仍然正确吗?
如果"correct"的意思是"perform a move",则不是。同样,如果要从命名变量中移动,则必须对其使用std::move
。这包括将其传递给右值引用参数。
唯一的例外是return <named_variable>;
语句,即使这样,"named_variable"也必须命名一个值,而不是引用(尽管C++20可能允许以这种方式隐式地从中移动右值引用变量(。
- 何时在引用或唯一指针上使用移动语义
- 如何从具有移动语义的类对象中生成共享指针
- 可以使用移动语义更改或改进此C++代码吗?
- c++在使用指针时移动语义
- 移动语义和深层/浅层复制之间有什么关系?
- std::unique_lock移动语义
- 移动语义和运算符 + 重载
- C++ 移动语义是否在任何情况下都能节省资源?
- 移动语义在这里如何工作?
- 使用移动语义:右值引用作为方法参数
- 在C++中使用移动语义的正确方法是什么?
- 移动语义 c++ 单链表
- C++:使用整数移动语义
- 当变量和参数名称匹配时,移动语义构造失败
- 在 C++11 中移动语义
- 方法冗余移动调用的移动语义
- 复制省略并在返回值中移动语义
- std::元组和移动语义
- 移动语义与返回shared_ptr?
- C++具有移动语义的可变参数工厂会导致运行时崩溃