以下代码无法在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)
答案 0 :(得分:13)
在C ++ 03和C ++ 98中,当将const引用绑定到rvalue(例如按值返回的函数)时,实现可以将引用直接绑定到rvalue,或者它可以复制rvalue并绑定对该副本的引用。由于auto_ptr
的复制构造函数采用非const引用,所以第二个选择只有在返回的rvalue不是const
限定的情况下才有效,但编译器仍然允许尝试这个,即使它赢了'工作。
在C ++ 11中,不允许使用这些额外副本,如果不需要转换,实现必须直接绑定到右值。
答案 1 :(得分:1)
Pre C ++ 11,至少,该标准需要一个对象 在这种情况下可复制。最后,语义为:
T const& t = f();
,其中f
按值返回T
为:
T tmp = f();
T const& t = tmp;
这需要复制构造函数。
在std::auto_ptr
的情况下,您遇到的问题
是复制构造函数被定义为采用非const
引用,表示您无法复制临时。一些
编译器(例如Microsoft)不强制执行此操作,这意味着
你的代码可以与他们合作,但这从根本上是非法的。
真正的问题是你在这里使用引用的原因。您 需要一个局部变量的方式;仅供参考 引入了一个额外的间接层。