草庐IT

c++ - shared_ptr 到数组 : should it be used?

coder 2023-04-24 原文

只是一个关于 shared_ptr 的小查询.

使用 shared_ptr 指向数组是一种好习惯吗?例如,

shared_ptr<int> sp(new int[10]);

如果不是,那为什么不呢?我已经知道的一个原因是不能增加/减少 shared_ptr。因此它不能像普通的指向数组的指针一样使用。

最佳答案

使用 C++17shared_ptr可用于管理动态分配的数组。 shared_ptr在这种情况下,模板参数必须是 T[N]T[] .所以你可以写

shared_ptr<int[]> sp(new int[10]);

来自 n4659,[util.smartptr.shared.const]

  template<class Y> explicit shared_ptr(Y* p);

Requires: Y shall be a complete type. The expression delete[] p, when T is an array type, or delete p, when T is not an array type, shall have well-defined behavior, and shall not throw exceptions.
...
Remarks: When T is an array type, this constructor shall not participate in overload resolution unless the expression delete[] p is well-formed and either T is U[N] and Y(*)[N] is convertible to T*, or T is U[] and Y(*)[] is convertible to T*. ...

为了支持这一点,成员类型 element_type 现在定义为

using element_type = remove_extent_t<T>;

可以使用 operator[] 访问数组元素

  element_type& operator[](ptrdiff_t i) const;

Requires: get() != 0 && i >= 0. If T is U[N], i < N. ...
Remarks: When T is not an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.


C++17 之前shared_ptr可以用于管理动态分配的数组。默认情况下,shared_ptr将调用 delete当没有更多的引用保留在托管对象上时。但是,当您使用 new[] 进行分配时您需要调用delete[] , 而不是 delete , 以释放资源。

为了正确使用shared_ptr对于数组,您必须提供自定义删除器。

template< typename T >
struct array_deleter
{
  void operator ()( T const * p)
  { 
    delete[] p; 
  }
};

如下创建shared_ptr:

std::shared_ptr<int> sp(new int[10], array_deleter<int>());

现在 shared_ptr将正确调用 delete[]销毁托管对象时。

上面的自定义删除器可以替换为

  • std::default_delete 数组类型的部分特化

    std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
    
  • 一个 lambda 表达式

    std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
    

此外,除非您确实需要托管对象的共享权限,否则 unique_ptr更适合这项任务,因为它对数组类型有部分特化。

std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]

C++ Extensions for Library Fundamentals 引入的变化

Library Fundamentals Technical Specification 提供了上面列出的另一个 C++17 之前的替代方案。 , 增加了 shared_ptr允许它在拥有对象数组的情况下开箱即用。 shared_ptr 的当前草案可以在 N4082 中找到此 TS 的计划更改。 .可通过 std::experimental 访问这些更改。命名空间,并包含在 <experimental/memory> 中标题。支持 shared_ptr 的一些相关更改对于数组是:

——成员类型的定义element_type变化

typedef T element_type;

 typedef typename remove_extent<T>::type element_type;

— 成员 operator[]正在添加中

 element_type& operator[](ptrdiff_t i) const noexcept;

— 与 unique_ptr 不同数组的部分特化,shared_ptr<T[]>shared_ptr<T[N]>将是有效的,两者都将导致 delete[]在托管对象数组上调用。

 template<class Y> explicit shared_ptr(Y* p);

Requires: Y shall be a complete type. The expression delete[] p, when T is an array type, or delete p, when T is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

关于c++ - shared_ptr 到数组 : should it be used?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13061979/

有关c++ - shared_ptr 到数组 : should it be used?的更多相关文章

  1. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  2. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  3. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  4. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  7. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  8. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  9. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  10. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

随机推荐