我正在研究一段代码,它有许多可能的故障点,导致它提前退出该功能。我正在与之交互的库要求将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
等替代方法,但您可以使用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.
}
答案 0 :(得分:27)
不要使用shared_ptr
或scoped_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::vector
。 vectors
中的元素在堆上分配,并且在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
或添加自定义删除器。