This is the most minimal example I could think of:
#import <Foundation/Foundation.h>
@interface ObjCClass:NSObject
@property void (^aBlockInner) ();
-(void)method;
-initWithBlock:(void (^)())aBlock;
@end
@implementation ObjCClass
- (void)method{
self->_aBlockInner();
}
-(instancetype)initWithBlock:(void (^)())aBlock
{
self->_aBlockInner = aBlock;
return self;
}
@end
struct cppClass{
cppClass(){
objCClassInstance = [[ObjCClass alloc] initWithBlock:^{
modifyY();
}];
[objCClassInstance method];
}
void modifyY() {
y++;
}
int y = 0;
ObjCClass* objCClassInstance;
};
int main()
{
cppClass a{};
NSLog(@"Y is:%d",a.y);
}
The member variable y is supposed to stay untouched as blocks are supposed to copy their “captures”. Though, the final print outputs:
Y is:1
Have I misunderstood Objective-C blocks?
To compile on a macOS do: clang++ main.mm -framework Foundation
Much more minimal example would be as follows:
This snippet has exactly the same "problem", and
imember variable gets changed within a block. This happens, because when you refer to member variables from inside member functions, this implicitly addsthispointer to the expression, so it's not actuallyimember variable that gets captured, butthispointer which encompasses it. The block above can be equivalently rewritten like this:The block makes a copy of the pointer to the same object, not object itself. However, if you had the owning object referred to by value, and not a pointer, you would not be able in fact, alter the object, because the copies a block makes are constant:
And this can only be done with use of the
__blockmodifier: