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

发布于 2024-09-10 01:38:31 字数 1312 浏览 7 评论 0原文

我正在研究一段代码,该代码有许多可能的故障点,导致其提前退出该函数。我正在交互的库要求将 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++,我想我遇到了这样一个情况:“如果你拥有的唯一工具是一把锤子,那么一切看起来都像钉子。”综合症。感谢您的反馈。

更新2 我想我应该更改问题并提供答案,以使其对于犯了与我相同错误的人来说更有价值。尽管有 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.
    }

I'm working on a section of code that has many possible failure points which cause it to exit the function early. The libraries I'm interacting with require that C-style arrays be passed to the functions. So, instead of calling delete on the arrays at every exit point, I'm doing this:

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

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

   //etc.
}

I wanted to use unique_ptr, but my current compiler doesn't support it and the reference count overhead doesn't really matter in this case.

I'm just wondering if anyone has any thoughts on this practice when interfacing with legacy code.

UPDATE I completely forgot about the shared_ptr calling delete instead of delete []. I just saw no memory leaks and decided to go with it. Didn't even think to use a vector. Since I've been delving into new (for me) C++ lately I'm thinking I've got a case of the "If the only tool you have is a hammer, everything looks like a nail." syndrome. Thanks for the feedback.

UPDATE2 I figured I'd change the question and provide an answer to make it a little more valuable to someone making the same mistake I did. Although there are alternatives like scoped_array, shared_array and vector, you can use a shared_ptr to manage scope of an array (but after this I have no idea why I would want to):

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.
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

GRAY°灰色天空 2024-09-17 01:38:31

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

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

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

Do not use shared_ptr or scoped_ptr to hold pointers to dynamically allocated arrays. shared_ptr and scoped_ptr use delete ptr; to clean-up when the pointer is no longer referenced/goes out of scope, which invoked undefined behaviour on a dynamically allocated array. Instead, use shared_array or scoped_array, which correctly use delete[] ptr; when destructing.

To answer your question, if you are not going to pass the smart pointer around, use scoped_array, as it has less overhead than shared_array.

Alternatively, use std::vector as the array storage (vectors have guaranteed contiguous memory allocation).

萌化 2024-09-17 01:38:31

使用 boost::scoped_array,如果您处理的是数组,则使用更好的 std::vector

Use boost::scoped_array, or even better std::vector if you are dealing with an array.

寄人书 2024-09-17 01:38:31

我强烈建议仅使用 std::vector。矢量中的元素在堆上分配,当矢量超出范围时,无论您在何处退出函数,这些元素都会被删除。

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

I highly recommend simply using a std::vector. Elements in vectors are allocated on the heap, and will be deleted when the vector goes out of scope, wherever you exit the function.

In order to pass a vector to legacy code requiring C-style arrays, simply pass &vectorName[0]. The elements are guaranteed to be contiguous in memory.

别念他 2024-09-17 01:38:31

针对 C++11 用户的一些说明:

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

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

C++11 中的 unique_ptr 有部分专门化来处理 new[]>删除[]。但不幸的是,它没有共同的行为。 shared_ptr 没有这样的专门化肯定是有充分理由的,但我没有寻找它,如果你知道,请分享它。

Some remarks for C++11 users:

For shared_ptr, there is in C++11 a default deleter for array types defined in <memory> and standard compliant (wrt the final draft) so it can be used without additional fancy deleters for such cases:

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

unique_ptr in C++11 has a partial specialization to deal with new[] and delete[]. But it does not have a shared behavior, unfortunately. Must be a good reason there is no such specialization for shared_ptr but I didn't look for it, if you know it, please share it.

梦开始←不甜 2024-09-17 01:38:31

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

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

This

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

is not a good practice, but causes undefined behaviour, as you allocate with operator new[], but shared_ptr uses operator delete to free the memory. The right thing to use is boost::shared_array or add a custom deleter.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文