c++ - 我应该移动 std::exchange ed 成员吗?
问题描述
可std::exchange
用于实现移动构造函数。这是来自 cppreference.com https://en.cppreference.com/w/cpp/utility/exchange#Notes的示例。
但是,可能的std::exchange
外观如下所示:
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
T old_value = std::move(obj);
obj = std::forward<U>(new_value);
return old_value; // can be copy (until C++17) or a move (C++17), right?
}
现在我的情况:
#include <string>
#include <utility>
struct MyClass
{
std::string m_str;
// some other non-primitive members of the class
MyClass(MyClass&& other) : m_str{ std::exchange(other.m_str, {}) } // enough?
// or
// : m_str{ std::move(std::exchange(other.m_str, {})) }
// ^^^^^^^^^^ do i need to move?
{}
MyClass& operator=(MyClass&& other)
{
this->m_str = std::exchange(other.m_str, {}); // enough?
// or
// this->m_str = std::move( std::exchange(other.m_str, {}) );
// ^^^^^^^^^^ do I need to move?
return *this;
}
};
正如我在代码中评论的那样,有机会按行移动或复制
m_str{ std::exchange(other.m_str, {}) }
this->m_str = std::exchange(other.m_str, nullptr);
所以,
- 我应该明确地
std::move
使用它们,以便我可以确保成员已 100% 移动到other
对象? - 如果Yes
std::exchange
,在这种情况下使用会更冗长吗?
我正在使用带有编译器标志 C++14 的 Visual Studio 2017。
解决方案
不,std::move
这里不需要使用。经验法则是 - 如果某些返回值未分配给变量,它将被移动。
template<class T, class U = T>
T exchange(T& obj, U&& new_value)
{
T old_value = std::move(obj);
obj = std::forward<U>(new_value);
return old_value; // will be moved if move constructor defined
// or even copy will be elided and will be no constructor call
}
与你所说的相反,这一举动在这里得到保证。C++17 更改了复制省略规则,但这是不同的
从这里你可以看到prvalue是:
函数调用或重载的运算符表达式,其返回类型为非引用,例如 str.substr(1, 2)、str1 + str2 或 it++
纯右值的属性(作为右值的子集)是(强调我的):
右值可用于初始化右值引用,在这种情况下,由右值标识的对象的生命周期会延长,直到引用范围结束。
当用作函数参数并且函数的两个重载可用时,一个采用右值引用参数,另一个采用左值引用对 const 参数,右值绑定到右值引用重载(因此,如果复制和移动构造函数都可用,右值参数调用移动构造函数,同样使用复制和移动赋值运算符)。
推荐阅读
- java - 如何使用 thymeleaf 从 html 选择中获取值和文本
- ruby - erb 模板在代码评估中打印换行符
- python - 如何使用 django rest 框架嵌套序列化器
- angular - ng2Charts/chart.js 将图表类型更改为一个正在影响许多图表
- ios - 显示具有独立姓名号码对的联系人
- php - 如何使用aws服务器解决codeigniter邮件成为垃圾邮件
- vue.js - Vuex store getter 总是返回 false
- angularjs - 使用 angular.js TypeError:无法读取未定义的属性“UserId”
- java - 如何在 Eclipse 中的断点后恢复通常的工作流程?
- javascript - 如何在 mat-table 中仅显示第一行的按钮