c++ - 通过unique_ptr或通过值传递对象以及如何实现

标签 c++ c++11 data-structures parameter-passing smart-pointers

我有一个案例,我不确定是否应该使用 unique_ptr 或按值传递对象。

假设我有 A 类,它有一个 B 类 vector ,而 C 类也有一个 B 类 vector 。每次我将 B 对象添加到 C 类中的 vector 时,都应该将其从 C 类 vector 中删除,反之亦然。当对象 C 被销毁时,B Vector 类中的所有对象都应添加到 A 类中的 B Vector

class B {
public:
    B();
    virtual ~B();
};

class A {
    C & c;
    std::vector<B> bs;
public:
    A(C & c ): c(c){};
    virtual ~A();
    void add(B b){
        bs.push_back(b);
        c.remove(b);
    }
    void remove(B b){
        bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
    }
};

class C {
public:
     A & a;
    std::vector<B> bs;
    C(A & a): a(a) {

    };
    virtual ~C(){
        for (B b : bs) {
                a.add(b);
                remove(b);
            }
    }

    void add(B b){
        bs.push_back(b);
        a.remove(b);
    }
    void remove(B b){
        bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());
    }
};

我的问题:

  1. 在这种情况下使用指针更好吗?我应该总是有一个唯一的 B 对象!换句话说,如果两个 b 对象的内容不同,它们仍然不同,因为内存中的地址不同。
  2. 我想在 C++ 11 中的 smart_pointers 的帮助下编写这段代码! shared_ptrunique_ptr 哪种类型更好? B 对象永远不会被两个对象所拥有,并且它始终只有一个所有者,因此我猜 unique_ptr 更好,但我不确定。
  3. 如何使用 unique_ptr 编写上面的代码?

最佳答案

  1. 如果复制构造 B 成本高昂,那么(智能)指针可能是个好主意(重新设计应用程序逻辑可能是另一种解决方案),

  2. 如果我理解正确的话,给定的 B 实例始终由单个所有者(AC)操纵。因此,std::unique_ptr 是一个合理的选择,

  3. 尝试以下实现。我还没有编译它,但我想你会明白的:)

.

class B {
public:
    B();
    virtual ~B();
};

class A {
    C & c;
    std::vector<std::unique_ptr<B>> bs;
public:
    A(C & c ): c(c){};
    virtual ~A();
    // http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
    // (c) Passing unique_ptr by value means "sink."
    void add(std::unique_ptr<B> b){
        c.remove(b);               // release the poiner from the other container
        bs.emplace_back(b.get());  // emplace the pointer in the new one
        b.release();               // emplacement successful. release the pointer
    }
    // http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
    // (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
    void remove(std::unique_ptr<B>& b){
        // @todo check that ther returned pointer is != bs.end()
        std::find(bs.begin(), bs.end(), b)->release();             // first release the pointer
        bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());  // then destroy its owner
    }
};

class C {
public:
    A & a;
    std::vector<std::unique_ptr<B>> bs;
    C(A & a): a(a) {

    };
    virtual ~C(){
        for (auto&& b : bs) {
            a.add(b);
            // a is going to call this->remove()...
            // unless calling this->remove() from "a"
            // while this is being destroyed is Undefined Behavior (tm)
            // I'm not sure :)
        }
    }
    // http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
    // (c) Passing unique_ptr by value means "sink."
    void add(std::unique_ptr<B> b){
        c.remove(b);               // release the poiner from the other container
        bs.emplace_back(b.get());  // emplace the pointer in the new one
        b.release();               // emplacement successful. release the pointer
    }
    // http://herbsutter.com/2013/06/05/gotw-91-solution-smart-pointer-parameters/
    // (d) Passing unique_ptr by reference is for in/out unique_ptr parameters.
    void remove(std::unique_ptr<B>& b){
        // @todo check that ther returned pointer is != bs.end()
        std::find(bs.begin(), bs.end(), b)->release();             // first release the pointer
        bs.erase(std::remove(bs.begin(), bs.end(), b), bs.end());  // then destroy its owner
    }
};

关于c++ - 通过unique_ptr或通过值传递对象以及如何实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33187647/

相关文章:

C 结构和 malloc 函数

c++ - 使用 QNetworkAccessManager 的 Qt 控制台应用程序

c++ - 使用 std::type_index 作为映射中的值

c++ - 为什么从静态方法访问非静态方法是糟糕的设计

algorithm - splay 树(自平衡树)背后的直觉

algorithm - 在不初始化向量的情况下访问元素。我需要额外的空间吗?

c++ - OpenCL C++ - 线程 64 后数组的内存管理错误

c++ - 我如何初始化 unordered_map< vector<int>>?

c++ - 无法解析类型 'GLchar'

c++ - 使用非静态数据成员和嵌套类构造函数的类内初始化时出错