How to index into a C ++ shared_ptr / unique_ptr array?
As inspired by Demonstrating a generic ptr array
I got the first two lines:
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) Can anyone show me how to access subsequent elements of my array and print them using a for loop?
My for loop prints nothing with MSVC V19 and g ++ v4.9 prints "john" but not "Paul" and "Mary" and then gives me a segmentation fault.
Now after doing some google / bing search I found some discussions suggesting to use unique_ptr
if I don't share it.
So, I had to experiment and this works:
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) Is there a way to print the array without hardcoding the length into a constant? I was hoping there was a way to get the new C ++ for loop syntax to work, but it only works on std::array
and std::vector
.
(3) Is there an easier way to initialize this array? Perhaps using an initializer list?
source to share
To access subsequent items use the function 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;
The problem with dereferencing shared_ptr
is that it will return string&
, but you want to access the underlying pointer in order to be able to index the next element.
You can also initialize the array shared_ptr
on construction using list initialization
std::shared_ptr<string> sp( new string[3]{"John", "Paul", "Mary"},
std::default_delete<string[]>() );
As far unique_ptr
as, as you noted, there is a partial specialization that will remove array types correctly. However, it does not store the length of the array, you will need to store it separately and pass it along with unique_ptr
. For one-line initialization, you can use the same syntax as above.
std::unique_ptr<string[]> up( new string[len]{"John", "Paul", "Mary"} );
However, neither shared_ptr
nor unique_ptr
can be used with range based loops. the specification of a range for which the operand must be either an array or must have member functions begin()
and end()
, or the start and end iterators of the range must be accessed by ADL using expressions begin(__range)
and end(__range)
respectively. None of these conditions satisfy either shared_ptr
or unique_ptr
containing an array.
Unless you have a good reason, you should just use std::vector<std::string>
, which saves you the trouble of keeping track of the length of the array separately. std::array<std::string, N>>
is also another option if you know the length of the array at compile time.
source to share
How do I index into a C ++
shared_ptr
/ arrayunique_ptr
?
You have already provided the code for unique_ptr
.
This works for 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";
source to share