移动构造函数是否C++过时?
Is C++ move constructor obsolete?
我编写了自己的字符串类型(Str
(来演示基本的构造函数,析构函数和赋值运算符;而且,我可以看到它们都在C++17中执行,除了移动构造函数。
显然,由于返回值优化 (RVO(,移动构造函数不再被大量使用。
移动构造函数是否仅在响应显式调用std::move
时才调用?
还能叫什么?
它是否因为 RVO 而大部分已经过时?
这是我的Str
类型:
struct Str {
Str(): p(nullptr) {}
Str(const char* s) { cout << "cvctor "" << s << ""n"; copy(s); }
Str(const Str& s): p(nullptr) { cout << "cpctor deep""<<s.p<<""n"; copy(s.p); }
Str( Str&& s) { cout << "mvctr shallow "" << s.p << ""n"; p = s.p; s.p=nullptr; }
const Str& operator=(const Str& s) { cout << "op=""<<s.p<<""n"; copy(s.p); return *this; }
const Str& operator=( Str&& s) { cout << "op= shallow ""<<s.p<<""n"; p=s.p; s.p=nullptr; return *this; }
~Str(){ if ( p != nullptr ) { cout << "dtor "" << p << ""n"; delete [] p; } }
private:
char* p = nullptr;
char* copy(const char* s)
};
不,一点也不
返回值优化并不是使用 move 构造函数的唯一点。每次要从rvalue
构造某种类型的值时,都是使用 move 构造函数的点。
你基本上会问两个问题。让我们从
移动构造函数是否仅在响应显式调用 std::move 时才调用?
移动构造函数和std::move
是切线相关的,但本质上是非常独立的。每次从相同类型的rvalue
初始化变量时,都会调用移动构造函数。另一方面std::move
可以明确地从所谓的lvalue
到这样的rvalue
,但这不是唯一的方法。
template<typename T>
void foo(T&& value) { // A so-called universal reference
T other_value = std::forward<T>(value);
}
foo( string{"some string"} ); // other_value is move initialized
你看,std::forward
是另一种获得rvalue
的方法。实际上,"some string"
还会导致上述代码中的rvalue
,类型为const char*
。
是时候来个间奏曲了。如果你听到rvalue
你可能会想&&
这是一个rvalue-reference
。这是微妙的不同。问题是给任何东西起名字都会使它成为lvalue
。所以下面的代码:
foo(string&& value) {
T other_value = value;
}
foo( "some_string" ); // other_value is STILL copy initialized
foo(string&& value) {
T other_value = std::move(value);
}
foo( "some_string" ); // other_value is now properly move initialized
考虑&&
的正确方法是,这样的引用可以用rvalue
初始化,但它本身并不总是这样的rvalue
。有关更多信息,另请参阅此处
它是否因为 RVO 而大部分已经过时?
除了 RVO 之外,还经常使用移动构造函数的两个值得注意的例子
进入方法参数
void foo(string value); // Somewhere else string& some_string = get_me_a_string(); foo( ::std::move(some_string) ); // Uses move constructor to initialize value some_string.clear(); // Most probably a no-op // Doing this leaves an empty some_string
请注意,在上面的示例中,
some_string
是引用这一事实与是否使用移动构造无关紧要。这是一个参考,以明确RVO可能并不总是可能的。在这种情况下,在some_string
被移出后,将保持未指定但有效的状态,这是一种奇特的方式,表示不会发生未定义的行为并且引用仍然有效。移入田间
class FooBar { string fooField; //Constructor FooBar( string bar ) : fooField( ::std::move(bar) ) // Uses move constructor to initialize fooField { } }
- 针对过时的模板显式实例化进行编译
- C++使用现代编译器编译的项目,但链接到过时的libstdc++
- 无法使用 openssl 服务器,因为密码已过时...什么的...ERR_SSL_VERSION_OR_CIPHER_MISMATCH
- 移动构造函数是否C++过时?
- decltype(auto) 是否使尾随返回类型过时?
- C++ 每次字符串通过时递减值
- 过时的编码(C )的确切含义是什么?
- 赫伯·萨特在 GotW #35 中关于字体名的代码笑话过时了吗?
- 检查动态链接库是否已过时
- 这个项目已过时
- 过时的含义
- VS2010:项目已过时
- 错误:过时的旧式基类初始值设定项
- 自lambdas进入C++以来,“回调”接口是否已过时
- HANDLE(IntPtr)已过时,kernel32.dll,安全文件句柄到IntPtr
- 简单的代码,看似随机的结果——这是由于过时的引用造成的吗
- 让年龄过时的结构
- 既然智能指针已经存在,那么使用C型指针是不是已经过时了
- TCP 连接已接受,但写入数据会导致它使用过时的连接
- 我是否仍然需要多线程或它已经过时了