“最重要的const”与auto_ptr:为什么代码不能编译?

时间:2013-10-29 15:20:26

标签: c++ c++11 auto-ptr c++98

以下代码无法在Visual C ++ 2008和2010上编译:

#include <memory>

struct A {};

      std::auto_ptr<A> foo()  { return std::auto_ptr<A>(new A); }
const std::auto_ptr<A> bar()  { return std::auto_ptr<A>(new A); }

int main()
{
   const std::auto_ptr<A> & a = foo(); // most important const

   const std::auto_ptr<A> & b = bar(); // error C2558:
                                       // class 'std::auto_ptr<_Ty>' :
                                       // no copy constructor available or copy
                                       // constructor is declared 'explicit'

                                bar(); // No error?
}

我期望“最重要的const”应用于变量“b”,然而,它不会编译,并且由于某种原因,编译器要求复制构造函数(这让我感到惊讶,因为应该没有副本涉及到这里)。对bar()的独立调用工作正常,这意味着,我想,b的初始化确实是问题。

这是编译器错误,还是标准中描述的真正的编译错误?

(也许它在C ++ 98中被禁止并在C ++ 11中被授权?)

注意:它在Visual C ++ 2012,gcc 4.6和Solaris CC(所有编译器......)上编译,但不是gcc 3.4,也不是XL C)

2 个答案:

答案 0 :(得分:13)

在C ++ 03和C ++ 98中,当将const引用绑定到rvalue(例如按值返回的函数)时,实现可以将引用直接绑定到rvalue,或者它可以复制rvalue并绑定对该副本的引用。由于auto_ptr的复制构造函数采用非const引用,所以第二个选择只有在返回的rvalue不是const限定的情况下才有效,但编译器仍然允许尝试这个,即使它赢了'工作。

在C ++ 11中,不允许使用这些额外副本,如果不需要转换,实现必须直接绑定到右值。

See also here.

答案 1 :(得分:1)

Pre C ++ 11,至少,该标准需要一个对象 在这种情况下可复制。最后,语义为:

T const& t = f();

,其中f按值返回T为:

T tmp = f();
T const& t = tmp;

这需要复制构造函数。

std::auto_ptr的情况下,您遇到的问题 是复制构造函数被定义为采用非const 引用,表示您无法复制临时。一些 编译器(例如Microsoft)不强制执行此操作,这意味着 你的代码可以与他们合作,但这从根本上是非法的。

真正的问题是你在这里使用引用的原因。您 需要一个局部变量的方式;仅供参考 引入了一个额外的间接层。