我从Objective-C背景来到C++ 11,而我正在努力解决的一件事是C++ 11 lambdas与Objective-C"blocks"的不同捕获语义.(见这里进行比较).
在Objective-C中,与C++一样,如果引用成员变量,则会隐式捕获self/ this指针.但是因为Objective-C中的所有对象都是有效的"共享指针",所以要使用C++术语,你可以这样做:
doSomethingAsynchronously(^{
someMember_ = 42;
});
Run Code Online (Sandbox Code Playgroud)
...并确保在执行块时,您正在访问其成员的对象将处于活动状态.你不必考虑它.C++中的等价物似乎是这样的:
// I'm assuming here that `this` derives from std::enable_shared_from_this and
// is already owned by some shared_ptr.
auto strongThis = shared_from_this();
doSomethingAsynchronously([strongThis, this] {
someMember_ = 42; // safe, as the lambda holds a reference to this
// via shared_ptr.
});
Run Code Online (Sandbox Code Playgroud)
在这里,您需要记住除了this指针之外还要捕获shared_ptr.是否有一些不那么容易出错的方法来实现这一目标?
在Boost.asio C++ 11示例中,有如下所示的片段:
void do_read()
{
auto self(shared_from_this());
socket_.async_read_some(boost::asio::buffer(data_, max_length),
[this, self](boost::system::error_code ec, std::size_t length)
{
if (!ec)
{
do_write(length);
}
});
}
Run Code Online (Sandbox Code Playgroud)
我理解为什么self需要指针来保持类活着(请参阅此问题),但我不明白为什么this指针也被捕获.只是这样作者可以写do_write(length)而不是self->do_write(length)或有其他原因吗?
在C++标准库中有一个移动构造函数和移动赋值运算符的特殊描述,它表示数据移出的对象在调用后保持有效但未指定的状态.为什么?我坦白地说不明白.这是我直觉上没有想到的.真的,如果我在现实世界中将某个地方从一个地方移动到另一个地方,我搬离的地方就是空的(是的,有效的),直到我搬到那里一些新东西.为什么在C++世界中应该有所不同?
例如,根据实现,以下代码:
std::vector<int> a {1, 2, 3};
std::vector<int> b {4, 5, 6};
a = std::move(b);
Run Code Online (Sandbox Code Playgroud)
可能等同于下一个代码:
std::vector<int> a {1, 2, 3};
std::vector<int> b {4, 5, 6};
a.swap(b);
Run Code Online (Sandbox Code Playgroud)
这真的是我没想到的.如果我将数据从一个向量移动到另一个向量,我期望向量移动数据为空(零大小).
据我所知,标准C++库的GCC实现在移动后将向量保持为空状态.为什么不将此行为作为标准的一部分?
将对象保留为未指定状态的原因是什么.如果是为了优化,那也有点奇怪.我可以对未指定状态的对象做的唯一合理的事情是清除它(好吧,我可以得到向量的大小,我可以打印它的内容,但由于内容未指定,我不需要它).因此,对象将以任何方式由我手动或通过调用赋值运算符或析构函数清除.我更喜欢自己清除它,因为我希望它能被清除.但那是双重呼唤clear.优化在哪里?
在该连接对象升压ASIO HTTP服务器实例的方法do_read,并do_write在shared_from_this()捕捉到地址的连接对象的寿命问题,如先前回答.仍然不清楚为什么在第67和88行代码shared_from_this()再次调用,而不是使用self:
40 auto self(shared_from_this());
41 socket_.async_read_some(boost::asio::buffer(buffer_),
42 [this, self](boost::system::error_code ec, std::size_t bytes_transferred)
43 {
....
67 connection_manager_.stop(shared_from_this());
```
Run Code Online (Sandbox Code Playgroud)