你能分配一个与 make_shared 等效的数组吗?
Posted
技术标签:
【中文标题】你能分配一个与 make_shared 等效的数组吗?【英文标题】:Can you allocate an array with something equivalent to make_shared? 【发布时间】:2012-12-10 03:05:59 【问题描述】:buffer = new char[64];
buffer = std::make_shared<char>(char[64]); ???
您可以使用make_shared<>()
为数组分配内存吗?
我可以:buffer = std::make_shared<char>( new char[64] );
但这仍然涉及调用 new,据我了解,make_shared
更安全、更高效。
【问题讨论】:
std::vector<char> buffer(64);
不,你不能做“std::make_sharedmake_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<T>
将其运行时参数转发给T
的构造函数。或者只是制作一个共享向量。
是的对不起我的意思是运行时。啊..这是个好主意,谢谢你教育了一个菜鸟!
支持洞察力,但您应该知道make_shared
不只是用于过早优化;它也是为了异常安全。 std::shared_ptr<T>(new T)
是一个危险信号,因为如果 shared_ptr
的构造函数恰好抛出 bad_alloc
异常,它会泄漏 new T
。
@PeteC 我们都是对的,因为问题案例比我简洁的评论所暗示的要微妙。问题在于诸如foo(sh_ptr(new T), sh_ptr(new U));
之类的表达式——在调用sh_ptr
的构造函数之间没有序列点,因此有效的构造顺序是new U
、new T
、sh_ptr(<ptr to T>)
、sh_ptr(<ptr to U>)
.如果中间两个调用中的任何一个抛出,则 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<char[]> b; b = std::make_unique<char[]>(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最有效的方法是使用下面的make_shared()
重载,它在 Boost 和 C++20 中可用。
template< class T >
shared_ptr<T> make_shared( std::size_t N );
【讨论】:
以上是关于你能分配一个与 make_shared 等效的数组吗?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在使用静态 constexpr 成员构造时 std::make_shared 与 new 不同? [复制]