将对象附加到智能指针矢量的最佳方法?

时间:2019-07-12 13:47:18

标签: c++ parameter-passing smart-pointers

考虑以下类别:

class A {
 public:
    A() {};
 protected:
    int m1;
    float m2;
    // ...
}

class B {
 public:
    B() { };
    void add1(std::shared_ptr<A> _obj) { 
        data.push_back(_obj); 
    };
    void add2(A* _obj) { 
        data.push_back(_obj); 
    };
    void add3(A& _obj) { 
        data.push_back(&_obj); 
    };
 private:
    std::vector<std::shared_ptr<A>> data;
}

addX中的哪种方法B更适合/最佳做法是将新的指针传递到向量中?考虑到data是非const智能指针的向量,我理解不可能通过const引用传递对象或智能指针,而不必“去const”它们,这是不可取的,并且认为是不好的实践。但是,除非我弄错了,否则所有这些方法最终都会实例化一个shared_ptr,然后将其复制到向量中?它们之间有什么区别?

2 个答案:

答案 0 :(得分:6)

如果要确保您的API清楚表明被调用者将要拥有所有权,则唯一可行的方法是add1。从签名中可以清楚地看到,您提供的任何内容都将由被呼叫者保留。

您可以使用std::move.emplace_back进行改进:

void add1(std::shared_ptr<A> _obj) 
{ 
    data.emplace_back(std::move(_obj)); 
}

add2具有误导性,因为原始指针可能会或可能不会暗示所有权。有人可以将指针传递给堆栈分配的变量。

add3也有同样的问题,但更容易引起误解,因为非const引用通常用于就地更改对象而不是获取其所有权。

答案 1 :(得分:3)

add2很糟糕,因为该函数会转移所有权,而这不应使用裸指针来完成。

add3更糟糕,因为即使在C ++ 11以前的约定中,通过传递引用来转移指针的所有权也是不习惯的。

add1很好。从函数声明中可以清楚地知道谁拥有资源(资源是共享的)。但是,您可以避免复制共享指针:

void add1(std::shared_ptr<A> _obj) { 
    data.push_back(std::move(_obj)); 
};