在Objective-C中使用std :: shared_ptr作为全局变量

时间:2014-11-26 19:12:03

标签: c++ objective-c objective-c++

我试图用我的c ++ .h文件和shared_ptr:s一起实现一个类。

为什么我的shared_ptr(totPtr)在方法之间保持其值?

当我使用double而不是类时的示例代码:

#include <memory>

static std::shared_ptr<myCppClass> totPtr;
static double tot; 


@implementation ViewController


- (void) createSelf
{
    totPtr = std::make_shared<myCppClass>(5); 
    tot = 10;   
}

此方法在createSelf:

之后调用
- (void)otherMethod 
{
    tot += 1; // works, tot = 11
    totPtr->doStuff(); // doesn't work, totPtr = nullptr 

}

tot2仍然具有值= 0,但是tot具有值= 10

2 个答案:

答案 0 :(得分:2)

对于全局变量,您应该在+[initialize]中初始化它,这是一种初始化任何全局变量的线程安全方法

+ (void)initialize {
    if (self == [ViewController self]) { // need to guard it so not get called again from subclass
        totPtr = std::make_shared<MyClass>();
        tot = 10;
    }
}

如果您在viewDidLoad初始化它们,它现在可能有效,但当您决定拥有ViewController的多个实例时,您会发现viewDidLoad的第二次调用将重置这些全局变量

但是通常你不想要全局变量,你想要实例变量/属性

@interface ViewController ()
@property (nonatomic) double tot;
@end

@implementation ViewController {
    std::shared_ptr<myCppClass> _totPtr;
}

你可以在另一个答案中描述的viewDidLoad中对它们进行初始化。

注意:我建议使用带有C ++类的ObjC属性(即shared_ptr)。因为每次通过属性访问它时,都需要调用setter / getter方法的开销,这可能需要复制shared_ptr,这是一个扩展操作(你应该总是通过方法参数中的引用传递shared_ptr,但是这在ObjC中并没有得到很好的支持。直接访问ivar可以避免开销。

答案 1 :(得分:1)

最好不要使用全局变量 - 最好使用属性。

但是如果你仍然需要它 - 不要使用init方法。

在你的代码上,我看不到谁在调用createSelf方法。

这里我展示了工作代码。

#import "ViewController.h"
#import "MyClass.h"
#include <memory>

static std::shared_ptr<MyClass> totPtr;
static double tot;

@interface ViewController ()
@property (nonatomic) std::shared_ptr<MyClass> p1;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self m1];
    [self m2];
    // Do any additional setup after loading the view, typically from a nib.
}

-(void) m1{
    totPtr = std::make_shared<MyClass>();
    self.p1 = std::make_shared<MyClass>();
    tot = 10;
}

-(void) m2{
    NSLog(@"id: %d",self.p1->id());
    NSLog(@"id: %d",totPtr->id());
}

- (IBAction)ev1:(id)sender {
    [self m2];
}

@end

<强>更新

如果要在init * method

中初始化该var,可以使用此方法
- (instancetype)initWithCoder:(NSCoder *)coder*