C++ std::move 和 unique_ptr 2020-11-01

新手寫出來的c++程序,估計到處都是可以優(yōu)化的坑!

第一點

    std::string str = "Hello";
    std::vector<std::string> v;

    cout<< "str.length is :" << str.length()<<endl;
    cout<< "str.capacity is :"<< str.capacity()<<endl;

    v.push_back(str); //使用push_back(const T&) 重載,調(diào)用時,會發(fā)生copy
    std::cout << "After push_back 1, str is \"" << str << std::endl;


    v.push_back(std::move(str));//會使用 push_back(T&&) 重載,不會發(fā)生copy,但是str 里面東西沒了
    std::cout << "After push_back 2, str is \"" << str << std::endl;

    std::cout << "The contents of the vector are \"" << v[0]
              << ", " << v[1] << std::endl;

    cout<< "str.length is :" << str.length()<<endl;
    cout<< "str.capacity is :"<< str.capacity()<<endl;

輸出如下:

str.length is :5
str.capacity is :15
After push_back 1, str is "Hello
After push_back 2, str is "
The contents of the vector are "Hello, Hello
str.length is :0
str.capacity is :15

第二點

定義了以下類和方法

class AAA{
private:
    int aaa=5;
public:
    ~AAA()=default;
    void show(){
        cout << "AAA.aaa = "<< aaa<<endl;
    }
};
void Test(std::unique_ptr<AAA> pp){
    pp->show();
}

然后就很自然的寫了以下調(diào)用

int main(int argc, char *argv[])
{
    std::unique_ptr<AAA> pp = std::make_unique<AAA>();
    Test(pp);//    <--------注意這里
}

一編譯就報錯.

In function ‘int main(int, char**)’:
main.cpp:127:12: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = AAA; _Dp = std::default_delete<AAA>]’
  127 |     Test(pp);
      |            ^

很奇怪,
我調(diào)用一個參數(shù)為:std::unique_ptr<AAA>的函數(shù),
按照要求,我傳入了一個 std::unique_ptr<AAA> 類型的變量 pp,卻無法編譯通過.

改成這樣就編譯通過了:

int main(int argc, char *argv[])
{
    std::unique_ptr<AAA> pp = std::make_unique<AAA>();
    Test(std::move(pp)); // <-------------添加了std::move調(diào)用

   
}

輸出為:

AAA.aaa = 5

然后繼續(xù),修改代碼,看看move后發(fā)生了什么,
代碼改為:

int main(int argc, char *argv[])
{
    std::unique_ptr<AAA> pp = std::make_unique<AAA>();
    Test(std::move(pp));

    if(pp ==nullptr){
        cout << "after call Test,pp is nullptr"<<endl;
    }else
    {
        cout << "after call Test,pp is not nullptr"<<endl;
    }
}

輸出如下:

AAA.aaa = 5
after call Test,pp is nullptr

這就對了,move以后沒了.
但還是有點區(qū)別:

  • String 在move以后,本身沒有變成null,但內(nèi)容沒有了.
  • unique_ptr<>,在move以后,本身變成了null.

第三點

實際上是接著第二點的

我發(fā)現(xiàn) std::unique_ptr<AAA> pp ,實際上是類unique_ptr<T>的一個實例,既然是類的實例,作為函數(shù)參數(shù)時,就應(yīng)該使用引用方式. 以及右值引用方式,于是就改成了下面的代碼(請手動忽略沒加const的問題)

void Test(std::unique_ptr<AAA>& pp){
    cout << "in Test(std::unique_ptr<AAA>& pp)" << endl;
    pp->show();
}
void Test(std::unique_ptr<AAA>&& pp){
     cout << "in Test(std::unique_ptr<AAA>&& pp)" << endl;
    pp->show();
}
int main(int argc, char *argv[])
{
    std::unique_ptr<AAA> pp = std::make_unique<AAA>();
    Test(pp); //<--------------注意這里

    if(pp ==nullptr){
        cout << "after call Test,pp is nullptr"<<endl;
    }else
    {
        cout << "after call Test,pp is not nullptr"<<endl;
    }
}

輸出為:

in Test(std::unique_ptr<AAA>& pp)
AAA.aaa = 5
after call Test,pp is not nullptr

看來調(diào)用的第一個引用參數(shù)的方法,由于沒有使用std::move,調(diào)用后pp 不是nullptr.

然后再試:

   std::unique_ptr<AAA> pp = std::make_unique<AAA>();

    Test(std::move(pp));//<--------------注意這里

     if(pp ==nullptr){
        cout << "after  call Test,pp is nullptr"<<endl;
    }else
    {
        cout << "after  call Test,pp is not nullptr"<<endl;
        pp->show();
    }

    if(pp.get() == nullptr){
        cout << "after  call Test,pp.get()  is nullptr"<<endl;
    }else
    {
        cout << "after  call Test,pp.get()  is not nullptr"<<endl;
        pp.get()->show();
    }



這次使用了std::move,調(diào)用了右值引用參數(shù)的方法,但是結(jié)果有點意外:

in Test(std::unique_ptr<AAA>&& pp)
AAA.aaa = 5
after  call Test,pp is not nullptr
AAA.aaa = 5
after  call Test,pp.get()  is not nullptr
AAA.aaa = 5

WTF,為啥 調(diào)用std::move之后竟然不變成nullptr.

不知對std::move的理解有問題還是實現(xiàn)有問題!!! 哭阿!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容