簡體   English   中英

使用 std::ref 傳遞共享指針是否安全?

[英]Is it safe to pass a shared pointer using std::ref?

我需要將包含上下文 object 的共享指針傳遞給回調 function 而不移動所有權,因為所有上下文對象都存儲在unordered_map中。

我使用std::ref將共享指針傳遞給來自父 function 的回調 function。

主 -> 從 map 獲取共享指針 -> 父 function(接受共享指針) -> 回調 function

void HTTPTransport::handleMessage(const evpp::TCPConnPtr &socket, std::shared_ptr<Connection> context,
                                  const std::variant<int, std::string> &message) {
                                      
    auto ctx = context->get();
    
    // Do Stuff
    
}

void HTTPTransport::handle(const evpp::TCPConnPtr &socket, std::shared_ptr<Connection> context) {
    ws->onMessage(std::bind(&HTTPTransport::handleMessage, this, std::ref(socket), std::ref(context), _1));
}

在這種情況下使用std::ref是否安全?

我記得在某處讀到應該避免引用共享指針,因為 memory 泄漏。

有一件事我忘了提。 指針可能在我通過時為空,因為有時在調用斷開回調時連接會從 map 中刪除....

這取決於。 Binding a reference to a local object (the shared pointer in this case) into a function object works if the lifetime of the referred object exceeds the lifetime of the callback funtion. 依賴這樣的假設是不安全的,因為如果假設是錯誤的,程序的行為將是不確定的。

在許多對回調的調用是異步的情況下,不能做出這樣的假設。

不,在您的實施中它是不安全的。 在這段代碼中:

void HTTPTransport::handle(const evpp::TCPConnPtr &socket, std::shared_ptr<Connection> context) {
    ws->onMessage(std::bind(&HTTPTransport::handleMessage, this, std::ref(socket), std::ref(context), _1));
}

context是一個局部變量,因此存儲對它的引用將在使用該引用時具有未定義的行為。 由於您的回調按值獲取context ,而handle也按值獲取上下文,因此您已經復制了shared_ptr兩次,因此通過引用存儲可能沒有什么好處。 將這兩種方法都更改為使用引用將意味着shared_ptr在調用std::bind時僅被復制一次(或者如果您根本不使用std::ref ):

void HTTPTransport::handleMessage(const evpp::TCPConnPtr &socket, const std::shared_ptr<Connection>& context,
                                  const std::variant<int, std::string> &message) {
    auto ctx = context->get();

    // Do Stuff
}

void HTTPTransport::handle(const evpp::TCPConnPtr &socket, const std::shared_ptr<Connection>& context) {
    ws->onMessage(std::bind(&HTTPTransport::handleMessage, this, socket, context, _1));
}

如果您始終只有一個指針所有者(unordered_map),那么聽起來您實際上並沒有從使用shared_ptr中獲得太多好處。 您最好在 map 中使用std::unique_ptr然后在方法之間傳遞引用:

void HTTPTransport::handleMessage(const evpp::TCPConnPtr &socket, Connection& context,
                                  const std::variant<int, std::string> &message) {              
    auto ctx = context.get();
    
    // Do Stuff
}

void HTTPTransport::handle(const evpp::TCPConnPtr &socket, Connection& context) {
    ws->onMessage(std::bind(&HTTPTransport::handleMessage, this, socket, std::ref(context), _1));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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