[英]Why wasn't std::string move constructor called?
我有這個例子:
#include <string>
#include <iostream>
class Test {
private:
std::string str;
public:
Test(std::string &&str_) :
str(str_)
{}
const std::string &GetStr()
{
return str;
}
};
int main(int argc, char *argv[])
{
std::string there("1234567890");
std::cout << "1. there: " << there << '\n';
Test t1(std::move(there));
std::cout << "2. there: " << there << '\n';
std::cout << "3. there: " << t1.GetStr() << '\n';
}
它給出了輸出
$ ./a.out
1. there: 1234567890
2. there: 1234567890
3. there: 1234567890
這是在linux上使用gcc 5.1.1。 雖然there
串會有效,但不確定的狀態移動后留下的,這似乎執行如果的std :: string移動構造函數被調用移動(而不是復制)的字符串。
如果我用str(std::move(str_))
替換initalizer str(str_)
,我得到這個輸出:
$ ./a.out
1. there: 1234567890
2. there:
3. there: 1234567890
這表明現在使用了std :: string移動構造函數,但為什么在我的第一個例子中沒有調用std::string(std::string &&)
?
你應該做
public:
Test(std::string &&str_) :
str(std::move(str_))
{}
str_
確實有一個名稱,是一個命名對象,所以它不會作為rvalue-reference傳遞給任何函數。
標准委員會做出的設計選擇可以防止將其視為右值,因此您無法無意中對其進行修改。 特別是: str_
do的類型是對string
的左值引用,但str_
不被視為rvalue,因為它是一個命名對象。
您必須通過添加對std::move
的調用來明確您的意圖。 這樣做表明你希望str_
成為右值,並且你知道這個選擇的所有后果。
因為左值參考總是贏! 這就是你需要明確指定std::move
。
允許通過模板或typedef中的類型操作形成對引用的引用,在這種情況下,引用折疊規則適用:對右值引用的rvalue引用折疊為rvalue引用,所有其他組合形成左值引用:
typedef int& lref;
typedef int&& rref;
int n;
lref& r1 = n; // type of r1 is int&
lref&& r2 = n; // type of r2 is int&
rref& r3 = n; // type of r3 is int&
rref&& r4 = 1; // type of r4 is int&&
取自這里 。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.