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