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

Why does passing self by reference result in a bad access error?

本文关键字:错误 访问 self 引用 为什么      更新时间:2023-10-16

下面的代码片段运行正常。我注册Objective-C函数mytestslot作为源自C++类thing的信号的回调。slot函数被周期性地调用,并且一切都表现良好。

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之间的根本差异,我没有把握,但我也不完全确定,因为我是一个完全的Objective-C新手!

因为引用是指向变量的指针,它伪装成在语法上与变量本身类似。

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

这个问题与self或Objective-C无关。

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

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