构造函数采用auto_ptr

时间:2013-10-28 19:07:00

标签: c++ initialization auto-ptr

我想编写一个带有构造函数的C ++类,它以auto_ptr作为参数,以便我可以将类实例从auto_ptr初始化为另一个实例:

#include <memory>

class A
{
public:
  A() {}
  A(std::auto_ptr<A> other) {}
};

std::auto_ptr<A> create()
{
  return std::auto_ptr<A>(new A());
}

void foo()
{
  A x = create();
  // A y ( create() );    // works
}

在gcc 4.6上使用g++ -c test.cpp编译此代码会产生以下错误消息:

test.cpp: In function ‘void foo()’:
test.cpp:17:16: error: no matching function for call to ‘std::auto_ptr<A>::auto_ptr(std::auto_ptr<A>)’
test.cpp:17:16: note: candidates are:
/usr/include/c++/4.6/backward/auto_ptr.h:260:7: note: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr_ref<_Tp>) [with _Tp = A]
/usr/include/c++/4.6/backward/auto_ptr.h:260:7: note:   no known conversion for argument 1 from ‘std::auto_ptr<A>’ to ‘std::auto_ptr_ref<A>’
/usr/include/c++/4.6/backward/auto_ptr.h:125:9: note: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp1>&) [with _Tp1 = A, _Tp = A]
/usr/include/c++/4.6/backward/auto_ptr.h:125:9: note:   no known conversion for argument 1 from ‘std::auto_ptr<A>’ to ‘std::auto_ptr<A>&’
/usr/include/c++/4.6/backward/auto_ptr.h:112:7: note: std::auto_ptr<_Tp>::auto_ptr(std::auto_ptr<_Tp>&) [with _Tp = A, std::auto_ptr<_Tp> = std::auto_ptr<A>]
/usr/include/c++/4.6/backward/auto_ptr.h:112:7: note:   no known conversion for argument 1 from ‘std::auto_ptr<A>’ to ‘std::auto_ptr<A>&’
test.cpp:7:3: error:   initializing argument 1 of ‘A::A(std::auto_ptr<A>)’

但是,如果我使用语法A y (create());来创建我的对象,它就会起作用。

我想知道为什么会发生这种情况,如果我有什么办法可以解决它。

编辑:我还要指出,如果我将构造函数签名更改为

  A(const std::auto_ptr<A>& other) {}

然后一切都很美妙,但是这并不是auto_ptr的所有权,因此没有我想要的语义。

编辑2:如果我使用赋值运算符执行相同的操作,即

A& operator=( std::auto_ptr<A> other) {}

然后我可以做

A x;
x = create();

为什么?

2 个答案:

答案 0 :(得分:7)

只允许一个隐式的,用户定义的转换。从另一个构造auto_ptr已经涉及通过辅助auto_ptr_ref类进行隐式转换,因此您无法从auto_ptr隐式构建自己的类。

通过使用直接初始化,其中一个转换是显式,并且只保留一个隐式的用户定义转换,这很好。

要“解决”缺少隐式转换,您可以修改构造函数以获取auto_ptr(非常量)引用,或将所有内容迁移到unique_ptr

答案 1 :(得分:0)

使用:

A(std::auto_ptr<A>& other)
              //  ^ Note the reference!
{
    // Assign interned auto_ptr member here, which you definitely should have
}