【问题标题】:Can you allocate an array with something equivalent to make_shared?你能分配一个与 make_shared 等效的数组吗?
【发布时间】:2012-12-10 03:05:59
【问题描述】:
buffer = new char[64];
buffer = std::make_shared<char>(char[64]); ???

您可以使用make_shared&lt;&gt;() 为数组分配内存吗?

我可以:buffer = std::make_shared&lt;char&gt;( new char[64] );

但这仍然涉及调用 new,据我了解,make_shared 更安全、更高效。

【问题讨论】:

  • std::vector&lt;char&gt; buffer(64);
  • 不,你不能做“std::make_shared(new char[64]);”。

标签: c++ c++11 shared-ptr make-shared


【解决方案1】:

make_shared的重点是将托管对象合并到共享指针的控制块中,

既然您正在处理 C++11,也许使用 C++11 数组会满足您的目标?

#include <memory>
#include <array>
int main()
{
    auto buffer = std::make_shared<std::array<char, 64>>();
}

请注意,您不能像从 new[] 获得的指针那样使用共享指针,因为std::shared_ptr(例如,与std::unique_ptr 不同)不提供operator[]。您必须取消引用它:(*buffer)[n] = 'a';

【讨论】:

  • 我无法在编译时指定数组的大小?
  • @JoshElias 你肯定可以在编译时。你的意思是运行时间吗?这将需要您自己的类将数组大小作为构造函数参数,因为make_shared&lt;T&gt; 将其运行时参数转发给T 的构造函数。或者只是制作一个共享向量。
  • 是的对不起我的意思是运行时。啊..这是个好主意,谢谢你教育了一个菜鸟!
  • 支持洞察力,但您应该知道make_shared只是用于过早优化;它也是为了异常安全。 std::shared_ptr&lt;T&gt;(new T) 是一个危险信号,因为如果 shared_ptr 的构造函数恰好抛出 bad_alloc 异常,它会泄漏 new T
  • @PeteC 我们都是对的,因为问题案例比我简洁的评论所暗示的要微妙。问题在于诸如foo(sh_ptr(new T), sh_ptr(new U)); 之类的表达式——在调用sh_ptr 的构造函数之间没有序列点,因此有效的构造顺序是new Unew Tsh_ptr(&lt;ptr to T&gt;)sh_ptr(&lt;ptr to U&gt;) .如果中间两个调用中的任何一个抛出,则 new U 被泄露。 herbsutter.com/gotw/_102
【解决方案2】:

您需要共享分配的内存吗?您可以改用 std::unique_ptr 和 C++14 上可用的 std::make_unique

auto buffer = std::make_unique<char[]>(64);

C++20 中将有一个std::make_shared 版本可用:

auto buffer = std::make_shared<char[]>(64);

【讨论】:

  • 即使您确实希望共享它,make_unique 也可以使用 std::shared_ptr&lt;char[]&gt; b; b = std::make_unique&lt;char[]&gt;(25);
  • @Thomas 是的,make_unique 可以正常工作。但是以这种方式初始化 shared_ptr 会花费你额外的内存分配。使用make_shared时可以避免这种情况。
  • @PaulGroke 是的,但为了完整起见,我要补充一点,保存的分配会带来轻微的风险weak_ptr, make_shared and memory deallocation
【解决方案3】:

这个怎么样?

template<typename T>
inline std::shared_ptr<T> MakeArray(int size)
{
    return std::shared_ptr<T>( new T[size], []( T *p ){ delete [] p; } );
}

auto  buffer = new char[64];
auto  buffer = MakeArray<char>(64);

【讨论】:

  • 创建新的shared_ptr 和使用make_shared 是有区别的,后者的原子操作少了1个,尽可能优先使用。
  • 此方法也不会为数组分配引用计数,因此需要两次调用内存管理器。
  • 考虑到 C++20 指日可待,这种“polyfill”允许我们编写非常接近于您选择的编译器支持 C++20 的 make_shared(size_t),开销将大大超过更干净、健壮的面向未来的代码。如果您将模板重命名为“make_shared_array”之类的名称,那么当您明年返回代码进行升级时,其意图就很明显了 ;-) 这极大地有助于使用可变结构缓冲区,因为许多系统调用都需要。其他变量数组方法生成阻塞强制转换警告=错误。
【解决方案4】:

最有效的方法是使用下面的make_shared() 重载,它在 Boost 和 C++20 中可用。

template< class T >
shared_ptr<T> make_shared( std::size_t N );

【讨论】:

    猜你喜欢
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    • 2018-03-18
    • 1970-01-01
    • 2019-03-19
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    相关资源
    最近更新 更多