程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 實戰c++中的智能指針unique_ptr系列-- unique_ptr與lambda的錯誤結合(尤其是捕獲lambda中的unique_ptr)

實戰c++中的智能指針unique_ptr系列-- unique_ptr與lambda的錯誤結合(尤其是捕獲lambda中的unique_ptr)

編輯:C++入門知識

實戰c++中的智能指針unique_ptr系列-- unique_ptr與lambda的錯誤結合(尤其是捕獲lambda中的unique_ptr)


lambda表達式是C++11新引入的東西,給我們帶來了很多的方便,使得代碼簡潔明了。

但是當我們把unique_ptr和lambda表達式結合的時候,錯誤就往往會出現,而且是致命的。

直接看看下面的代碼:

#include "stdafx.h"
#include 
#include 
#include 

class Message {
public:
     Message() {}
};

int main(int argc, char* argv[])
{
     std::vector>messages;

     for (int i = 0; i < 1000; i++) {
          std::unique_ptr testMess;
          messages.push_back(std::move(testMess));  
     }

     std::for_each(messages.begin(), messages.end(),
                [](std::unique_ptr testMess) {     
        // do something stupid
     });

   return 0;
}

但是不幸的是,這段代碼編譯就會產生錯誤,但也算是幸運的:

d:\program files (x86)\microsoft visual studio 14.0\vc\include\algorithm(24): error C2280: “std::unique_ptr>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)”: 嘗試引用已刪除的函數

簡單分析
我們在lambda表達式中使用的是按值傳遞;
按值傳遞就會產生副本,就會產生一個unique_ptr的copy;
但是我們知道的,這顯然是錯誤。

解決方法很簡單,就是按引用傳遞替代按指針傳遞:

#include 
#include 
#include 
#include 

class Message {
public:
    Message() {}
};

int main(int argc, char* argv[])
{
    std::vector>messages;

    for (int i = 0; i < 1000; i++) {
        std::unique_ptr testMess;
        messages.push_back(std::move(testMess));
    }

    std::for_each(messages.begin(), messages.end(),
        [](std::unique_ptr &testMess) {
        // do something stupid
    });

    return 0;
}

上面的內容只是算個開胃菜,如果我們想在lambda表達式中捕獲unique_ptr,又會如何呢?

十分優雅的寫下如下代碼:

#include
#include
#include
int main()
{
    auto str = std::make_unique("my string");
    auto lambda = [capturedStr = std::move(str)]{
        std::cout << *capturedStr.get() << std::endl;
    };
    lambda();
    return 0;
}

一切很完美,編譯 運行 輸出正確。

接下來,再干點事兒:

#include
#include
#include
int main()
{
    auto str = std::make_unique("my string");
    auto lambda = [capturedStr = std::move(str)] {
        std::cout << *capturedStr.get() << std::endl;
        auto str2 = std::move(capturedStr);
        std::cout << *str2 << std::endl;
    };
    lambda();
    return 0;
}

恭喜你,編譯錯誤。

原因為何呢?為什麼 auto str2 = std::move(capturedStr);會錯誤呢?
這就是lambda表達式的知識了:
lambda表達式默認是const的,我們當然不能std::move一個const對象。

解決方法也很簡單,就是加入關鍵字mutable
程序如下,運行完好:

#include
#include
#include
int main()
{
    auto str = std::make_unique("my string");
    auto lambda = [capturedStr = std::move(str)] ()mutable {
        std::cout << *capturedStr.get() << std::endl;
        auto str2 = std::move(capturedStr);
        std::cout << *str2 << std::endl;
    };
    lambda();
    return 0;
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved