2017-03-04 415 views
1

我想要真正从C++ 98移到C++ 11和更新的版本。我已将大部分新东西包裹起来,但我仍不确定unique_ptr的正确用法。在类成员中正确使用unique_ptr

考虑下面的例子,其中类A有一个unique_ptr成员(我以前会使用原始指针!)。这个成员变量应该在用户需要时通过在其他地方调用一个函数(而不是类的一部分)来分配。这是正确的用法吗?如果不是,最好的选择是什么?

class A { 
private: 
    unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt.reset(std::move(StaticFuncSomewhereElese::generateMyType())); 
    } 
}; 

MyType* StaticFuncSomewhereElese::generateMyType() { 
    MyType* temp = new MyType(...); 
    //do stuff to temp (read file or something...) 
    return temp; 
} 
+2

你不需要'std :: move'那里,原始指针不能被移动。 – emlai

+0

@tuple_cat但是,这编译和运行完美 –

+0

@SaeidYazdani虽然你不需要它。而是使用'std :: make_unique()'。 –

回答

3

你的代码工作正常(虽然冗余* move可省略),但它会更好,尽早构建unique_ptr

classss A { 
private: 
    std::unique_ptr<MyType> mt; 
public: 
    void initStuff() { 
     mt = StaticFuncSomewhereElese::generateMyType(); 
    } 
}; 

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() { 
    auto temp = std::make_unique<MyType>(…); 
    // `make_unique` is C++14 (although trivially implementable in C++11). 
    // Here's an alternative without `make_unique`: 
    // std::unique_ptr<MyType> temp(new MyType(…)); 

    //do stuff to temp (read file or something...) 
    return temp; 
} 

这种方式很明显的回报调用者必须删除generateMyType的值,并且内存泄漏的可能性较小(例如,如果generateMyType提前返回)。

*的move是多余的,因为:

  1. 原始指针不能移动。
  2. 无论如何,generateMyType()表达式的结果已经是一个右值。
+2

请注意,问题标记为C++ 11,因此可能值得一提的是,直到C++ 14才引入'std :: make_unique'。 – user2079303

3

这是正确的用法吗?

除了std::move是多余的,是的,这是正确的。这是多余的,因为a)复制裸指针,不管它们是左值还是右值,以及b)函数不返回引用,所以返回值已经是右值,因此不需要转换。

但还有改进的余地。我特别推荐从工厂函数返回一个唯一指针:

std::unique_ptr<MyType> StaticFuncSomewhereElese::generateMyType() 

这可以防止temp从如果初始化抛出异常泄漏,并使其更难为工厂的用户意外泄漏返回指针。