你可以将shared_ptr用于C风格数组的RAII吗?

时间:2010-07-16 15:29:15

标签: c++ raii shared-ptr

我正在研究一段代码,它有许多可能的故障点,导致它提前退出该功能。我正在与之交互的库要求将C样式的数组传递给函数。因此,我没有在每个出口点调用数组上的delete,而是这样做:

void SomeFunction(int arrayLength)
{
   shared_ptr<char> raiiArray(new char[arrayLength]);
   pArray = raiiArray.get();

   if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }

   //etc.
}

我想使用unique_ptr,但我当前的编译器不支持它,并且引用计数开销在这种情况下并不重要。

我只是想知道在与遗留代码接口时是否有人对这种做法有任何想法。

更新我完全忘记了shared_ptr来电delete而不是delete []。我刚看到没有内存泄漏,并决定采用它。甚至没想过用矢量。因为我最近一直在钻研新的(对我来说)C ++我认为我有一个案例“如果你拥有的唯一工具是锤子,那么一切看起来都像钉子一样。”综合征。感谢您的反馈。

UPDATE2 我想我会改变这个问题并提供一个答案,让对我犯同样错误的人更有价值。虽然有scoped_arrayshared_arrayvector等替代方法,但您可以使用shared_ptr来管理数组的范围(但在此之后我不知道为什么我会想要于):

template <typename T>
    class ArrayDeleter
    {
    public:
        void operator () (T* d) const
        {
            delete [] d;
        }
    };

void SomeFunction(int arrayLength)
    {
       shared_ptr<char> raiiArray(new char[arrayLength], ArrayDeleter<char>());
       pArray = raiiArray.get();

       if(SomeFunctionThatRequiresCArray(pArray) == FAILED) { return; }

       //etc.
    }

6 个答案:

答案 0 :(得分:27)

不要使用shared_ptrscoped_ptr来保存指向动态分配的数组的指针。当指针不再被引用/超出范围时,shared_ptr和scoped_ptr使用delete ptr;进行清理,这会在动态分配的数组上调用未定义的行为。相反,使用shared_array或scoped_array,它们在破坏时正确使用delete[] ptr;

要回答您的问题,如果您不打算通过智能指针,请使用scoped_array,因为它的开销低于shared_array

或者,使用std::vector作为数组存储(向量已保证连续的内存分配)。

答案 1 :(得分:15)

如果您正在处理数组,请使用boost::scoped_array,甚至更好std::vector

答案 2 :(得分:7)

我强烈建议您只使用std::vectorvectors中的元素在堆上分配,并且在vector超出范围时将被删除,无论您何处退出该函数。

为了将vector传递给需要C风格数组的遗留代码,只需传递&vectorName[0]即可。这些元素保证在内存中是连续的。

答案 3 :(得分:6)

C ++ 11用户的一些评论:

对于shared_ptr,在C ++ 11中有一个默认的删除器,用于在<memory>中定义的数组类型和符合标准的(最终草案),因此可以在没有其他花式删除器的情况下使用它。例:

std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>()); 
C ++ 11中的

unique_ptr具有部分专业化,可以处理new[]delete[]。但不幸的是,它没有共享行为。必须是shared_ptr没有这种专业化的好理由,但我没有找到它,如果您知道,请分享。

答案 4 :(得分:5)

答案 5 :(得分:3)

shared_ptr<char*> raiiArray(new char[arrayLength]);

不是一个好习惯,但会导致未定义的行为,因为您使用运算符new[]分配,但shared_ptr使用operator delete释放内存。正确使用的是boost::shared_array或添加自定义删除器。