3
boost::shared_array<char const *> x(new char const *[n]);

In the line above (n is integer number not greater than 100) I'm creating char const**(const char**) and putting it to smart pointer x for arrays to be deleted when x is deleted. And for me it is clearly how and why this work.

boost::shared_array<char const *> x = new char const *[n];

Now lets take a look to second line. Here in my opinion we do exactly the same as in first case. Yes at first glance we may seem that here we constructing x via NULL(default value of shared_array constructors parameter) then calling operator=, but this is mistake, and as I know in this case instead of operator= will be called constructor with pointer created by new opeartor.

But in spit of this I'm getting error C2440: 'initializing' : cannot convert from 'const char **' to 'boost::shared_array<T>

The only problem I see this is the explicit constructor of boost::shared_array<T>. But I don't know what is the problem? Why does explicit constructor cause this error? And if the problem is not in explicit constructor, then where, why?

Mihran Hovsepyan
  • 10,810
  • 14
  • 61
  • 111

3 Answers3

3

Your guess is correct.

What you're trying to do in the second line is implicitly calling the constructor: you want the C++ compiler to realize that there is a constructor available that accepts a T* and use it. However, since the constructor is marked as explicit, it cannot be invoked this way.

See for example the discussion at http://www.go4expert.com/forums/showthread.php?t=20756.

telewin
  • 1,102
  • 8
  • 17
2

Yes, the "problem" is that the T* constructor for shared_array is explicit. That forbids constructing with =.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
1

Now lets take a look to second line. Here in my opinion we do exactly the same as in first case. Yes at first glance we may seem that here we constructing x via NULL(default value of shared_array constructors parameter) then calling operator=, but this is mistake, and as I know in this case instead of operator= will be called constructor with pointer created by new opeartor.

That's not entirely true. Here's what actually happens in the general case. Suppose you have

struct A
{
   /*explicit*/ A(int){}

};

A a = 7;

This isn't actually equivalent to A a(7). In the A a = 7 initialization, you call 2 constructors, the constructor that takes int to create a temporary, and the copy constructor to initialize a. Of course this is redundant in most cases and the compiler is allowed to omit the copy-constructor call (that is explicitly mentioned in the standard) but nonetheless it requires you to have one regardless of whether it decides to omit the call or not.

struct A
{
   /*explicit*/ A(int){}
   private: A(A const &){}  
};

A a = 7;

Now this will be a compile-time error. If you add some tracing messages to both constructors, you'll most likely see that the copy constructor doesn't get called anyway, but that doesn't matter - it must be there and accessible.

As to why explicit hinders you to call the above syntax must be clear now - because that constructor is called implicitly to initialize the temporary, not a.

HTH and Cheers, :)

Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434