为什么通过引用传递self会导致错误的访问错误?

时间:2013-12-04 11:16:45

标签: c++ objective-c c++11 lambda signals

以下代码段运行正常。我将Objective-C函数mytestslot注册为源自C ++类thing的信号的回调。槽函数会定期调用,一切都很好。

struct CPPMembers { // pimpl related stuff for C++ members
    Thing thing;
    boost::signals2::scoped_connection con;
};

@implementation MyChannelClass

-(void)mytestslot:(float)num{
    NSLog(@"Slot call = %0.2f", num);
}

-(id)init
{
    self = [super init];
    if (self) {
        //Allocate storage for C++ members
        _cppMembers = new CPPMembers;

        auto slotLambda = [self](float n){[self mytestslot:n];};
        _cppMembers->con =  _cppMembers->thing.addSubscriber(  slotLambda   );
    }


    return self;
}
...

但是,当我将slotLambda更改为通过引用捕获时。 。

auto slotLambda = [&](float n){[self mytestslot:n];};

触发信号时,我在运行时得到EXC_BAD_ACCESS。我猜这可能是由于Objective-C的self和C ++的this之间的根本区别,我不理解,但后来我不完全确定,因为我是一个完整的目标-C newby!

2 个答案:

答案 0 :(得分:1)

因为引用是指向伪装成在变量本身的语法行为的变量的指针。

self的地址是什么?在x86架构上,它将是堆栈上的参数。在arm和x64上,它将是一个寄存器。无论哪种方式,一旦堆栈在-init返回后展开,引用将引用垃圾。

答案 1 :(得分:0)

此问题与self或Objective-C无关。

在C ++中采用lambda通过引用捕获变量并以lambda(或其副本)比它创建的函数更长的方式存储它是没有意义的。

这是因为lambdas捕获的变量(通过值或通过引用)必须具有自动存储持续时间(即局部变量),并且在C ++中未定义的行为是在它指向的变量退出之后访问引用范围。