C++ 是C++;移动构造函数是否过时?
我编写了自己的字符串类型(C++ 是C++;移动构造函数是否过时?,c++,move-semantics,C++,Move Semantics,我编写了自己的字符串类型(Str)来演示基本的构造函数、析构函数和赋值运算符;而且,除了move构造函数,我可以看到它们都在C++17中执行 显然,由于返回值优化(RVO),move构造函数不再被广泛使用 是否仅在显式调用std::move时调用move构造函数 什么时候可以叫它? 它是否因为RVO而过时 这是我的Str类型: struct Str { Str(): p(nullptr) {} Str(const char* s) { cout << "cvctor \""
Str
)来演示基本的构造函数、析构函数和赋值运算符;而且,除了move构造函数,我可以看到它们都在C++17中执行
显然,由于返回值优化(RVO),move构造函数不再被广泛使用
是否仅在显式调用std::move
时调用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)
};
结构Str{
Str():p(nullptr){}
Str(const char*s){完全不能
返回值优化不是使用移动构造函数的唯一点。每次要从rvalue
构造某种类型的值时,都会使用移动构造函数
你基本上一次问两个问题。让我们从
是否只在显式调用std::move时调用move构造函数
move构造函数和std::move
是相切的,但本质上是非常独立的。每次从同一类型的rvalue
初始化变量时,都会调用move构造函数。另一方面std::move
可以显式地从所谓的左值
到这样的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
思考&
的正确方法是,这样的引用可以用rvalue
初始化,但它本身并不总是这样的rvalue
。有关更多信息,请参阅
它是否因为RVO而过时 两个值得注意的例子是,除了RVO之外,move构造函数还经常被使用
- 进入方法参数
请注意,在上面的示例中,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
是一个引用这一事实与是否使用move构造无关。它是一个引用,用于明确RVO可能并不总是可能的。在这种情况下,在从some_string
移动之后,将处于未指定但有效的状态,这是一种奇特的方式表示不会发生未定义的行为,并且引用仍然有效some_string
- 进入农田
class FooBar { string fooField; //Constructor FooBar( string bar ) : fooField( ::std::move(bar) ) // Uses move constructor to initialize fooField { } }
向后推几次std::vector
@Nemo说的话,除了然后将noexcept
添加到移动构造函数中,然后再次尝试向量测试。有趣!为什么noexcept会有这么大的不同?问题是关于对std::move
@AlexeyAndronov的隐式调用。我想你是指隐式调用移动构造函数?没有对std::move
的隐式调用。啊哈!多个条件返回语句将阻止RVO并触发移动构造函数调用,如下所述:
class FooBar {
string fooField;
//Constructor
FooBar( string bar )
: fooField( ::std::move(bar) ) // Uses move constructor to initialize fooField
{ }
}