C++ 为什么要在lambdas中捕获它以及指向它的共享指针?

C++ 为什么要在lambdas中捕获它以及指向它的共享指针?,c++,c++11,boost,lambda,boost-asio,C++,C++11,Boost,Lambda,Boost Asio,在Boost.asio C++11示例中,有以下代码段: 我理解为什么需要使用self指针来保持类的活动状态(请参阅),但我不理解为什么还捕获这个指针。这仅仅是为了让作者可以编写do\u write(length)而不是self->do\u write(length),还是有其他原因呢?如果不捕获这个,就不能从lambda内部调用类的方法(例如do\u write)。或访问成员变量。诚然,你可以改为写self->do_write(),但它既不优雅,也可能较慢(因为涉及共享ptr。这里给出的答案是

在Boost.asio C++11示例中,有以下代码段:


我理解为什么需要使用
self
指针来保持类的活动状态(请参阅),但我不理解为什么还捕获
这个
指针。这仅仅是为了让作者可以编写
do\u write(length)
而不是
self->do\u write(length)
,还是有其他原因呢?

如果不捕获
这个
,就不能从lambda内部调用类的方法(例如
do\u write
)。或访问成员变量。诚然,你可以改为写
self->do_write()
,但它既不优雅,也可能较慢(因为涉及
共享ptr

这里给出的答案是绝对的错误!你不应该两个都通过!以下是您应该如何根据您的代码执行此操作,而无需传递
this

void do_read()
{
  auto self(shared_from_this());
  socket_.async_read_some(boost::asio::buffer(data_, max_length),
      [self](boost::system::error_code ec, std::size_t length)
      {
        if (!ec)
        {
          self->do_write(length);
        }
      });
}

实际上,您应该使用
std::bind
,而不是lambdas。这将使您的代码更加紧凑。

仅就速度问题展开讨论:的答案似乎表明,在旧的/糟糕的编译器上,取消智能指针的引用可能比取消原始指针的引用慢,但在现代编译器上应该几乎没有惩罚。@dshepherd:fair,但如果禁用优化(例如调试模式),它可能会更慢。@shep I dunno:这是一个指向易于确定对象的常量指针。共享ptr由存储在objecr中的弱ptr构建,在第一次从对象创建共享ptr时初始化。我无法想象优化器在这种情况下不会有问题,更不用说从中共享的数据可以为空!我发现有必要捕捉到这一点,以便调用类方法来处理较旧(可能有缺陷)的GCC版本。没有使用叮当声编译的代码很好。@Yakk你的意思是
shared\u ptr
可以为空ptr吗?由于
shared\u from\u,因此该
是一个继承的成员函数,不可能从已由
shared\u ptr
管理的有效函数调用(无错误)。一句话:方便。Violet Giraffe的回答对我来说似乎完全有意义。“你能详细说明一下它是怎么错的,以及为什么你的更好吗?”昆廷引用“如果没有这个,你就不能从lambda内部调用类的方法”。这完全是错误的
self
可以完全执行此的功能。另外,假设从这个共享的速度较慢也是错误的(尽管他说“可能”,这是一个无用的、防御性的、流动的回答)
operator->
不做任何检查,因此最小的优化将消除性能上的任何差异。这个答案并没有提供任何有用的信息,而是基于假设和概括的错误信息。很抱歉这么严厉,但我很惊讶。在阅读文档之后,应该没有任何性能影响。但是,您确实会失去直接成员访问权限(即,无
this->
self->
)。@Quentin如果您对直接成员访问的意思是,我们不必明确地编写
this
来访问成员,那实际上是肤浅的。编译器使之成为可能。实际上,不编写
this
会让编译器从内到外检查是否存在这样的成员,直到它发现
this
有这样的成员并使用它。这就是为什么gcc有时会告诉你,
This
没有被捕获,因为它“猜测”你正在
This
中寻找一个成员。嗯,这没有什么好处。这只是“减少文字”,只是一种风格。对我来说,使用
self
在语义上更清晰。是的,我知道它是如何工作的。但问题是“为什么拍摄这部电影”,答案是“只看外表”。如果您不想直接访问会员,则必须捕获此,仅此而已。
void do_read()
{
  auto self(shared_from_this());
  socket_.async_read_some(boost::asio::buffer(data_, max_length),
      [self](boost::system::error_code ec, std::size_t length)
      {
        if (!ec)
        {
          self->do_write(length);
        }
      });
}