std::shared_ptr<T[]> VS std::array<T,大小>/std::vector<T>

std::shared_ptr<T[]> VS std::array<T, size>/std::vector<T>

提问人:Maksim Kononykhin 提问时间:6/16/2023 更新时间:6/16/2023 访问量:106

问:

所以,我有一个问题,我找不到答案。在C++中,共享指针具有一个构造函数,该构造函数可以包含原始数组(例如,std::shared_ptr<int[]>。

与 std::array 或 std::vector 相比,使用它有什么好处?

尝试搜索,询问gpt。至于 std::vector,有一种建议是可以使用 std::shared_ptr 避免内存分配,但这并不能解释为什么在有 std::array 时使用它

C++ C++17 标准 共享 PTR

评论

0赞 digby280 6/16/2023
它归结为所有权模型。如果需要具有共享所有权的数组,则需要一个shared_ptr。如果一个对象将拥有数组,则可以使用 std::arry 或 std::vector。
0赞 Pepijn Kramer 6/16/2023
使用 std::shared_ptr 时要小心,通常 std::unique_ptr 是更好的模型。最后,他们都会分配。std::array<> 在堆上,std::vector<T>/std::make_unique<T[]>/std::make_shared<T[]> 在堆上分配。std::vector<T> 也可以重新分配到在运行时添加项的时间。如果您只需要分配一次,则可以使用 std::make_unique<std::array<T,N>>
0赞 Pepijn Kramer 6/16/2023
我还不太相信 chatGPT 的答案。您要解决的实际问题是什么?
0赞 user4581301 6/16/2023
大多数时候,您应该避免使用数组而使用 或,但有时您仍然需要一个原始数组。标准库只是填补空白,以便覆盖案例。std::arraystd::vector
1赞 Evg 6/16/2023
一个好处是,你可以创建未初始化的数组。 将始终初始化值。请参见 和 。std::shared_ptr<int[]>std::unique_ptr<int[]>std::vector<int>std::make_shared_for_overwrite()std::make_unique_for_overwrite()

答:

5赞 HolyBlackCat 6/16/2023 #1

与所有其他列出的选项不同,它要求在编译时知道大小,并且不将元素存储在堆上(除非它本身在堆上)。std::array

std::vector<T>可以使用编译时未知的大小,在这种情况下应是默认选择。它始终将元素存储在堆上。

std::unique_ptr<T[]>可以认为是精简的.它不知道它的大小,这节省了一点点内存(通常是,而通常是)。std::vectorsizeof(std::unique_ptr<T[]>)sizeof(void *)sizeof(std::vector<T>)3 * sizeof(void *)

因为它不存储它的大小,所以它能开箱即用的事情很少:它不能被复制(只能移动),它不能插入或删除元素,等等。如果您单独存储尺寸,您可以手动完成所有这些操作,但只需执行额外的步骤即可。std::vector

std::shared_ptr<T[]>添加了一个额外的功能 - 共享所有权,就像任何其他 .std::unique_ptr<T[]>std::shared_ptr<??>

1赞 Yusuf Khan 6/16/2023 #2

容器和智能指针的使用取决于使用情况和设计:

std::vector creates a dynamic array of objects on heap
std::array creates a static array of object on stack, size known at compile time
std::shared_ptr<int[]> keeps the reference count of the resource, here resource is a pointer to an array

std::array 在堆栈上,如果使用限制在范围内并且大小在编译时已知,则数组就可以了。

当您想在函数、容器、线程(多线程安全对象或 const)之间共享资源的所有权时,shared_ptr 是合适的。但是使用shared_ptr并不意味着我们可以避免分配,您需要传递它管理的资源指针。

至于向量,它在堆上分配数据,但需要注意向量本身不应该超出范围,否则析构函数会释放资源,因为它没有像shared_pointer那样的引用计数。

如果使用 vector,则至少完成一次分配。

如果使用 array,则它在堆栈上,因此不会进行分配。

shared_ptr需要一个指针,该指针必须分配到某个地方。其他分配是控制块。因此,在使用 std::make_shared 之前进行 2 次分配,可以优化分配次数。