28

我正在处理一段代码,它有许多可能的故障点,导致它提前退出函数。我正在与之交互的库要求将 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_array,shared_array和之类的替代方法vector,但您可以使用 ashared_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.
    }
4

6 回答 6

28

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

要回答您的问题,如果您不打算传递智能指针,请使用scoped_array,因为它的开销比shared_array.

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

于 2010-07-16T15:34:20.323 回答
15

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

于 2010-07-16T15:34:04.927 回答
7

我强烈建议简单地使用std::vector. in 的元素是在堆上分配的,并且在超出范围vectors时将被删除,无论您退出函数。vector

为了将 a 传递vector给需要 C 样式数组的遗留代码,只需传递&vectorName[0]. 保证元素在内存中是连续的。

于 2010-07-16T15:38:10.953 回答
6

给 C++11 用户的一些注意事项:

对于shared_ptr,在 C++11 中有一个用于定义数组类型的默认删除器<memory>并符合标准(最终草案),因此在这种情况下无需额外花哨的删除器即可使用它:

std::shared_ptr<char> raiiArray(new char[arrayLength], std::default_delete<char[]>()); 

unique_ptr在 C++11 中有部分专业化来处理new[]delete[]. 但不幸的是,它没有共同的行为。一定是一个很好的理由没有这样的专业,shared_ptr但我没有寻找它,如果你知道,请分享它。

于 2013-08-17T12:41:31.547 回答
5

boost::scoped_ptr这个。

于 2010-07-16T15:30:42.300 回答
3

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

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

于 2010-07-16T15:37:25.907 回答