如何索引到c++ shared_ptr/unique_ptr数组

How to index into C++ shared_ptr/unique_ptr array?

本文关键字:ptr shared 数组 unique c++ 何索引 索引      更新时间:2023-10-16

灵感来自共享ptr数组的演示

我得到了前两行工作:

std::shared_ptr<string> sp( new string[3], []( string *p ) { delete[] p; } );
*sp = "john";
auto p = &(* sp);
++p = new string("Paul");
++p = new string("Mary");
for(auto q = &(*sp); q <= p; q++) cout << *q << endl;

(1)有人能告诉我如何访问我的数组的后续元素,并打印出他们与for循环?

我的for循环在MSVC V19和g++ v4.9中不打印任何东西,打印"john"但不打印"Paul"answers"Mary",然后给我一个分段错误。

现在经过更多的谷歌/bing搜索,我发现一些讨论建议我应该使用unique_ptr,如果我不分享它。

所以我做了更多的实验,这是可行的:

  const int len=3;
  std::unique_ptr<string[]> up( new string[len] ); // this will correctly call delete[]
  up[0] = "john";
  up[1] = "paul";
  up[2] = "mary";
  for(int ii = 0; ii < len; ++ii) cout << up[ii] << endl;

(2)有没有一种方法来打印数组没有硬编码的长度常数?我希望有一种方法可以使新的c++ for循环语法工作,但它似乎只适用于std::arraystd::vector

(3)是否有更简单的方法来初始化这个数组?也许有一个初始化列表?

使用shared_ptr::get成员函数访问后续元素

std::shared_ptr<string> sp( new string[3], std::default_delete<string[]>() );
sp.get()[0] = "John";
sp.get()[1] = "Paul";
sp.get()[2] = "Mary";
for(auto q = sp.get(); q < sp.get() + 3; q++) cout << *q << endl;

解引用shared_ptr的问题是它会返回一个string&,但是你想要访问底层指针,以便能够索引到下一个元素。

你也可以在构造shared_ptr数组时使用列表初始化

std::shared_ptr<string> sp( new string[3]{"John", "Paul", "Mary"}, 
                            std::default_delete<string[]>() );

对于unique_ptr,正如您所注意到的,存在部分专门化,可以正确地删除数组类型。但是,它不存储数组的长度,您需要单独存储它,并将其与unique_ptr一起传递。对于单行初始化,您可以使用与上述相同的语法。

std::unique_ptr<string[]> up( new string[len]{"John", "Paul", "Mary"} );

然而,shared_ptrunique_ptr都不能用于基于范围的for循环。for范围的指定要求操作数要么是数组,要么必须具有begin()end()成员函数,或者该范围的开始迭代器和结束迭代器必须由ADL分别使用表达式begin(__range)end(__range)获得。包含数组的shared_ptrunique_ptr都不满足这些条件。


除非你有很好的理由不这样做,否则你应该只使用std::vector<std::string>,这将节省你单独跟踪数组长度的麻烦。如果您在编译时知道数组的长度,那么std::array<std::string, N>>也是另一种选择。

在c++ 17中,operator[]是为shared_ptr<T[]> (link)定义的。在此之前,unique_ptr有,但shared_ptr没有。

所以,下面的代码可以工作:

std::shared_ptr<string[]> sp(new string[3]);
    sp[0] = "John";
    sp[1] = "Paul";
    sp[2] = "Mary";
    for(int i =0; i< 3; i++)
    {
        cout<<sp[i]<<"n";
    }

注意,它是为shared_ptr<T[]>定义的,而不是为shared_ptr<T>定义的,即当你有一个动态分配的数组时。此外,我已经删除了您的自定义删除器,因为您的删除器类似于编译器将使用的默认删除器,但是您可以自由添加它。

对于你的第二个查询-能够使用新的c++ For循环(基于范围的For循环),你不能直接使用这个智能指针,因为基于范围的For循环只适用于具有begin(), end(), operator++, operator*()operator!=定义的容器(链接)。最简单的方法是使用预先分配大小的std::vector。如。vector<T> sp(3)vector<T> sp; sp.reserve(3)。这和你的智能指针方法一样有效。要获得底层内存,您可以使用vector<T>::data() eg。sp.data()。这将给你一个包含3个元素的动态C数组(一般为n个元素)。

如何索引到c++ shared_ptr/unique_ptr数组?

您已经显示了unique_ptr的代码。

这适用于shared_ptr .

std::shared_ptr<string> sp( new string[3], []( string *p ) { delete[] p; } );
sp.get()[0] = "string 1";
sp.get()[1] = "string 2";
sp.get()[2] = "string 3";