【发布时间】:2015-06-11 11:42:44
【问题描述】:
我正在使用 asio 独立 1.10.6 和 vs2015 rc。
vs2015 支持 unique_ptr 捕获。所以我写了一些代码如下:
auto data = std::make_unique<std::string>("abc");
auto buffer = asio::buffer(data->c_str(), data->size());
asio::async_write(s, buffer, [data = std::move(data)](
const asio::error_code& error, size_t byte_transferred) mutable {
do_something(std::move(data), error, byte_transferred);
});
但是当我编译代码时,编译器说:
错误 C2280: .... 试图引用已删除的函数
据我了解,它说我尝试复制 lambda,因为 lambda 捕获了 std::unique_ptr,所以它是不可复制。
让我困惑的是为什么 asio 想要复制 lambda 但不移动 lambda。
我的代码有什么问题?如何解决?
===========================
完整代码为:
void do_something(std::unique_ptr<std::string> data) { }
void compile_failed() {
asio::io_service io_service;
asio::ip::tcp::socket s(io_service);
auto data = std::make_unique<std::string>("abc");
auto buffer = asio::buffer(data->c_str(), data->size());
asio::async_write(s, buffer, [data = std::move(data)](const asio::error_code& error,
size_t byte_transferred) mutable {
do_something(std::move(data));
});
}
template<typename T > struct lambda_evil_wrap {
mutable T ptr_;
lambda_evil_wrap(T&& ptr) : ptr_(std::forward< T>(ptr)) {}
lambda_evil_wrap(lambda_evil_wrap const& other) : ptr_(std::move(other.ptr_)) {}
lambda_evil_wrap & operator=(lambda_evil_wrap& other) = delete;
};
void compile_success_but_very_danger() {
asio::io_service io_service;
asio::ip::tcp::socket s(io_service);
auto data = std::make_unique<std::string>("abc");
auto buffer = asio::buffer(data->c_str(), data->size());
lambda_evil_wrap<std::unique_ptr<std::string>> wrapper(std::move(data));
asio::async_write(s, buffer, [wrapper](const asio::error_code& error,
size_t byte_transferred) mutable {
do_something(std::move(wrapper.ptr_));
});
}
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}
作为代码,如果我将 unique_ptr 包装到一个可复制的对象中,编译就可以了。 但是 lambda_evil_wrap::lambda_evil_wrap(lambda_evil_wrap const& a) 真的很烂而且不安全。不知道asio作者是否写了一些代码如下:
Handler handler2(handler);
handler(...); // Crash here
【问题讨论】:
-
std::ref(lambda)? -
你确定是这个问题吗?编译器还说什么吗?始终在问题中包含完整且未经编辑的错误日志。
-
当然 std::ref(lambda) 可以让编译器满意。但是代码是错误的。当函数返回时,数据将被释放并在do_something中崩溃。
-
Joachim Pileborg:我确信这是因为 asio 希望处理程序可复制。以下代码有效: std::shared_ptr<:string> data2(std::move(data)); asio::async_write(... [data2](...){});
-
奇怪的是只有 io_context::post 需要“移动赋值”,但是像 asio::async_connect 或 stable_timer::async_wait 这样的东西可以接受“移动构造函数”。
标签: c++ c++11 lambda boost-asio unique-ptr