Copy constructor not called by synthesized device of properties in Objective-C ++ code

We all know how little documented Objective-C ++ is. I cannot find anything about this, but it is also difficult for me to find suitable unambiguous search conditions. So, Stackoverflow to the rescue (hopefully)!

I have a C ++ class that has an instance inside the Objective-C (++) class (and I have a project parameter allowed to call constructors / destructors).

All this works fine until I try to open the instance using the @synthesize d property. I am doing this with the assign property (since the Obj-C save counter is not applicable). The property seems to work, except when I install the instance, I expect the copy constructor to be involved. In fact, I see that a temporary instance is being created (the copy constructor is called). But the copy constructor on the ivar instance is not called. The values ​​are "magically" set. I assume the @synthesize d code does something like memcpy as a last step. This is normal for C struct s, but not so useful for C ++ class es, where the correctness of the code depends on copy constructors and assignment operators that are invoked accordingly.

Has anyone looked deeper into it, made it work, or confirmed that you cannot store C ++ objects as ivars in the Obj-C (++) class and have copy constructors called @synthesize d real estate?

(I can post sample code for all of this if necessary, but even the minimum version is a screenshot or so).

+4
source share
2 answers

Uhm, if I'm not confused, it is reasonable that the copy constructor is not called. Do you expect the Ivar to be magically destroyed and replicated? I assume against C ++ rules. If the synthesized setter is conceptual

 -(void)setFoo:(Foo)foo_{ foo=foo_; } 

then operator= should be called, not the copy constructor.

At the same time , operator= also not called bummer (10.6.4, gcc 4.2.1.)! Here is an example code:

 #import <Foundation/Foundation.h> class Foo{ int a,b; public: Foo():a(0),b(0){NSLog(@"default constructor for %p",this);} Foo(const Foo&foo):a(foo.a),b(foo.b){NSLog(@"copy constructor for %p",this);} Foo& operator=(const Foo& foo){ NSLog(@"assignment operator for %p",this); a=foo.a; b=foo.b; return *this; } }; @interface Bar:NSObject { Foo foo; } @property (assign) Foo foo; @end @implementation Bar @synthesize foo; @end int main(){ NSAutoreleasePool *pool=[[NSAutoreleasePool alloc] init]; Bar* bar=[[Bar alloc] init]; Foo foo; bar.foo=foo; [pool drain]; } 

Save it in boo.mm , I had:

 $ g++ -fobjc-call-cxx-cdtors boo.mm -framework Foundation $ ./a.out 2010-09-04 12:32:06.570 a.out[24352:903] default constructor for 0x10010cdc8 2010-09-04 12:32:06.572 a.out[24352:903] default constructor for 0x7fff5fbff7e0 2010-09-04 12:32:06.573 a.out[24352:903] copy constructor for 0x7fff5fbff7d0 $ 

Now I had an explicit installer, which I wrote above, instead of @synthesize Foo , I correctly had

 $ ./a.out 2010-09-04 12:42:22.206 a.out[24417:903] default constructor for 0x10010cdc8 2010-09-04 12:42:22.209 a.out[24417:903] default constructor for 0x7fff5fbff7e0 2010-09-04 12:42:22.210 a.out[24417:903] copy constructor for 0x7fff5fbff7d0 2010-09-04 12:42:22.210 a.out[24417:903] assignment operator for 0x10010cdc8 

Clan source code for generating this synthesized setter, see GenerateObjCSetter . There, he eventually checks to see if the C ++ assignment operator is needed. I would say that this is a gray area, not well documented, but is currently being implemented ...

+4
source

The general rule with properties is if you need certain behavior that the default template template that is generated cannot provide you, write your own method -setFoo: for your foo property, which does what you need. Automatic synthesis of properties is intended for the general case, they will not be used everywhere. In these cases, specify your own setter or getter for this property.

0
source

All Articles