C ++从函数返回shared_ptr值

时间:2017-11-24 12:50:43

标签: c++ arrays templates shared-ptr

首先,我正在尝试创建自己的Vector类(基于STL Vector),只是为了练习一些C ++。不幸的是,当我开始使用shared_ptr时遇到了一些问题。

template <class T>
class MyVector{
    std::shared_ptr<T> p_array;
    int p_size; 
    int p_capacity; 
public:
    MyVector();
    void pushBack(T);
    T getBegin();      
};

构造

template <class T>
MyVector<T>::MyVector() : p_capacity(2), p_size(0) {
    std::shared_ptr<T> p_array(new T[p_capacity], std::default_delete<T[]>() );     
}

pushBack方法

template <class T>
void MyVector<T>::pushBack(T m_element) {
    p_array.get()[p_size] = m_element;
    p_size++;
}

getBegin方法

template <class T> 
T MyVector<T>::getBegin() {
    return p_array.get()[0];
}

然后在主

int main(){
    MyVector<int> test;
    test.pushBack(4);
    cout << "Begin of vector: " << test.getBegin();
}

用g ++编译后得到的是Segmentation fault(core dumped) 我想得到的只是添加到矢量的第一个元素的值。如果它在原始指针上完成,一切正常。

1 个答案:

答案 0 :(得分:1)

您遇到的问题存在一些问题。

第一个是你的构造函数创建一个与成员同名的 local 变量,这意味着它不会分配给成员。将构造函数更改为:

template <class T>
MyVector<T>::MyVector() : p_capacity(2), p_size(0) {
    p_array(new T[p_capacity], std::default_delete<T[]>() );     
}
然而,

会导致编译错误,因为在调用类构造函数的主体之前已经构造了成员变量(在这种情况下使用默认构造函数),并且您无法再次构造它。因此,最简单的方法是编译这些代码并且#34;工作&#34;是使用作业:

template <class T>
MyVector<T>::MyVector() : p_capacity(2), p_size(0) {
    p_array = std::shared_ptr<T>(new T[p_capacity], std::default_delete<T[]>() );     
}

但请注意,这有点误导,因为shared_ptr<T>通常表示它包含指向单个元素的指针。从C ++ 17开始,已经调整了数组智能指针的规则,以便您也可以使用shared_ptr<T[]>

但是:正如Richard Critten所指出的,unique_ptr在这种情况下可能更合适,因为你的MyVector类是数组的唯一所有者。

事实上,std::unique_ptr支持T[]作为模板参数,可以简化代码:

首先,您可以将您的班级声明更改为:

class MyVector{
    std::unique_ptr<T[]> p_array; //clearer that it is holding an array
    // rest remains unchanged

并且您的构造函数可以(使用C ++ 14 std::make_unique)变为:

template <class T>
MyVector<T>::MyVector() : p_capacity(2), p_size(0) {
    p_array = std::make_unique<T[]>(p_capacity);     
}

std::unique_ptroperator[]也有重载,这意味着你也可以移除.get()pushBackgetBegin),例如:< / p>

template <class T> 
T MyVector<T>::getBegin() {
    // should check first that p_size is bigger 0!
    return p_array[0];
}