我得到了前两行:
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”和“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::array
和std::vector
。
(3)有没有更简单的方法来初始化这个数组?也许有一个初始化列表?
答案 0 :(得分:2)
要访问后续元素,请使用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&
,但您希望能够访问基础指针,以便能够索引到下一个元素。 / p>
您还可以在构建时使用列表初始化
初始化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_ptr
和unique_ptr
都不能与基于范围的for循环一起使用。范围的specification要求操作数要么是数组,要么必须具有begin()
和end()
成员函数,或者范围的开始和结束迭代器必须可以通过ADL分别使用表达式begin(__range)
和end(__range)
。 shared_ptr
或包含数组的unique_ptr
都不满足这些条件。
除非你有充分的理由不这样做,否则你应该使用std::vector<std::string>
,这样可以省去分别跟踪数组长度的麻烦。如果在编译时知道数组的长度,std::array<std::string, N>>
也是另一种选择。
答案 1 :(得分:2)
在C ++ 17中,为operator[]
(link)定义了shared_ptr<T[]>
。在此之前,这里是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循环仅适用于具有begin()
,{{ 1}},end()
,operator++
和operator*()
定义(link)。
最简单的方法是使用具有预分配大小的std :: vector。例如。 operator!=
或vector<T> sp(3)
。这将与您的智能指针方法一样有效。要获得基础内存,可以使用vector<T> sp; sp.reserve(3)
例如。 vector<T>::data()
。这将为您提供3个元素(通常为n个元素)的动态C数组。
答案 2 :(得分:1)
如何索引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";