6

以下代码无法在 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 上编译)

4

2 回答 2

13

在 C++03 和 C++98 中,当将 const 引用绑定到右值(例如按值返回的函数)时,实现可以将引用直接绑定到右值,也可以复制右值并绑定对该副本的引用。由于auto_ptr的复制构造函数采用非常量引用,因此只有在返回的右值const不合格但编译器仍然允许尝试此操作时,此第二选择才有效,即使它不起作用。

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

另请参阅此处。

于 2013-10-29T15:36:31.897 回答
1

至少在 C++11 之前,该标准要求对象在此上下文中是可复制的。最后,语义:

T const& t = f();

,其中按值f返回 a T,是:

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

这需要一个复制构造函数。

在 的情况下std::auto_ptr,您看到的问题是复制构造函数被定义为采用非常量引用,这意味着您不能复制临时值。一些编译器(例如 Microsoft)不强制执行此操作,这意味着您的代码可以与它们一起使用,但从根本上说是非法的。

真正的问题是你为什么在这里使用引用。您需要以一种方式或另一种方式使用局部变量;该参考仅引入了额外的间接层。

于 2013-10-29T16:00:43.470 回答