簡體   English   中英

為什么沒有調用std :: string移動構造函數?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM