4

I saw the following code,

#include <new>
#include <memory>
using namespace std;

class Fred;  // Forward declaration
typedef  auto_ptr<Fred>  FredPtr;

class Fred {
public:
  static FredPtr create(int i)
  { 
    return new Fred(i); // Is there an implicit casting here? If not, how can we return
                        // a Fred* with return value as FredPtr?
  }
private:
  Fred(int i=10)      : i_(i)    { }
  Fred(const Fred& x) : i_(x.i_) { }
  int i_;
};

Please see the question listed in function create.

Thank you

// Updated based on comments

Yes, the code cannot pass the VC8.0 error C2664: 'std::auto_ptr<_Ty>::auto_ptr(std::auto_ptr<_Ty> &) throw()' : cannot convert parameter 1 from 'Fred *' to 'std::auto_ptr<_Ty> &'

The code was copied from the C++ FAQ 12.15.

However, after making the following changes,

replace 
  return new Fred(i);
with
  return auto_ptr<Fred>(new Fred(i));

This code can pass the VC8.0 compiler. But I am not sure whether or not this is a correct fix.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
q0987
  • 34,938
  • 69
  • 242
  • 387

3 Answers3

6

std::auto_ptr does have a constructor that takes a raw pointer as its argument, but that constructor is explicit and cannot be used as a converting constructor.

This code will not compile.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 3
    Having implicit conversion to an `auto_ptr` would be pretty insane considering the ownership semantics of `auto_ptr` – CodesInChaos Jan 01 '11 at 22:22
  • Yah, just checked to be sure right after posting my previous answer- doesn't compile for me too. Thanks – Kos Jan 01 '11 at 22:25
  • @ToAll, the original code in the book doesn't pass the compiler of VS8.0 -- thank you – q0987 Jan 04 '11 at 02:51
3

No, no such implicit conversion exists. It turns out that this is actually a good thing, though. For example, consider this code:

void MyFunction(const std::auto_ptr<Fred>& myFred) {
   /* ... do something to Fred. */
}

int main() {
    Fred* f = new Fred;
    MyFunction(f); // Not legal, but assume it is.
    f->doSomething();
}

Here, if you could pass a raw pointer to a Fred into MyFunction, then when that function returned and the temporary auto_ptr object was cleaned up, the memory you allocated in main() would be reclaimed, and the call to f->doSomething() would probably cause a segfault. Making the auto_ptr constructor explicit is a safeguard against this; you don't want to accidentally acquire exclusive ownership of a resource when someone else thinks they already have that access.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
0

The fixed version of the code (return std::auto_ptr<Fred>(new Fred())) is correct and valid C++. However, I'm not sure what the create() function buys you in that creating a std::auto_ptr<T> should be within the skill set of any C++ programmer. Likewise, I'm not clear what typedefing std::auto_ptr<Fred> to FredPtr buys you, other than a need to look up what a FredPtr really is.

Max Lybbert
  • 19,717
  • 4
  • 46
  • 69