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?

+3


source to share


2 answers


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.

+2


source


How do I index into a C ++ shared_ptr

/ array unique_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";

      

+1


source







All Articles