【发布时间】:2011-10-14 15:57:51
【问题描述】:
考虑这段代码:
#include <memory>
#include <iostream>
class A
{
public:
A(int data) : data_(data)
{ std::cout << "A(" << data_ << ")" << std::endl; }
~A() { std::cout << "~A()" << std::endl; }
void a() { std::cout << data_ << std::endl; }
private:
int data_;
};
class B
{
public:
B(): a_(new A(13)) { std::cout << "B()" << std::endl; }
~B() { std::cout << "~B()" << std::endl; }
std::function<void()> getf()
{
return [=]() { a_->a(); };
}
private:
std::shared_ptr<A> a_;
};
int main()
{
std::function<void()> f;
{
B b;
f = b.getf();
}
f();
return 0;
}
这里看起来我正在按值捕获a_ 共享指针,但是当我在 Linux (GCC 4.6.1) 上运行它时,会打印出来:
A(13)
B()
~B()
~A()
0
显然,0 是错误的,因为 A 已经被破坏了。看起来this 实际被捕获并用于查找this->a_。当我将捕获列表从[=] 更改为[=,a_] 时,我的怀疑得到了证实。然后打印正确的输出并且对象的生命周期与预期的一样:
A(13)
B()
~B()
13
~A()
问题:
此行为是由标准指定的、实现定义的还是未定义的?还是我疯了,完全不同?
【问题讨论】:
-
我认为按照标准,a_ 通常会解析为 this->a_,除非您明确告诉它复制 a_。
-
对我来说似乎完全合法 - 范围内的唯一变量是
this。如果一个指针只是神奇地解除了成员引用,那将是令人惊讶的!不过,这是一个很好的问题,也是对孩子们的一个很好的警告,不要鲁莽地使用惰性捕获[=]/[&]。