"most important const"与auto_ptr:为什么代码无法编译?

The "most important const" vs. auto_ptr: Why the code does not compile?

本文关键字:代码 为什么 编译 ptr important most const auto      更新时间:2023-10-16

以下代码不能在 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上编译。

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

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

另请参阅此处。

至少在

C++11 之前,标准要求对象在这种情况下可复制。 最后,语义:

T const& t = f();

,其中 f 按值返回T为:

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

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

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

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