【问题标题】:Passing a class object with trivial copy constructor, but no output?使用简单的复制构造函数传递一个类对象,但没有输出?
【发布时间】:2012-10-24 07:46:44
【问题描述】:

我用 GCC 和 Clang 试过这个程序,但都没有输出

#include <iostream>

struct A {
  A(){}

  template<typename T>
  A(T &) {
    std::cout << "copied!";
  }
};

void f(...) { }

int main() {
  A a;
  f(a);
}

根据我的标准阅读,这个程序应该输出"copied!"。谁能告诉我是我弄错了还是这两个编译器的错误?

【问题讨论】:

  • 这不是一个“简单的复制构造函数”。
  • 只是一般性评论:在不到 10 分钟的学习后对 Johannes Schaub 的问题投反对票 - litb 并不是一件很聪明的事情。
  • "根据我阅读的标准,这个程序应该输出“复制!”。" 我查看了标准,但我找不到它甚至会说话的地方关于可变参数与对象(或其他任何事情)的行为。那是哪里?
  • @durron597 不同之处在于您可以控制对象是动态存储(A* a = new A)还是自动存储(A a)。 C++ 在这方面更强大,而你对它的反应是没有受过教育的。
  • 这个问题没有得到我的 +1,因为它没有解释为什么你认为行为应该不同。没有实际引号的“标准这么说”是没有用的。

标签: c++ c++11 language-lawyer ellipsis


【解决方案1】:

您所期望的似乎是标准定义的行为。

模板函数不会阻止创建复制构造函数/赋值运算符。所以模板函数不会阻止一个类被认为是“可简单复制的”。但是,当实际复制它们时,它们确实参与了重载解决,因此它们可以进行干预。由于本例中的a 是一个非常量左值,它比A(const A&amp;) 更适合签名A(A&amp;)。所以它调用了模板函数。

(虽然你为什么不费心在你的问题中解释所有这些,但我不明白,因为你显然做了你的研究。)

但是,考虑到这种极端情况有多小,我不会四处依赖这种行为来强制可平凡复制的类不被平凡复制。

【讨论】:

  • 这是错误的。不是复制构造函数的模板化构造函数不会妨碍在传递相同类类型的非常量左值时调用它。
  • @Xeo:不,但如果还有一个合成的 [非模板] 复制构造函数具有相同的签名,那么在重载决议中将优先考虑。这个模板“复制构造函数”甚至永远不会被实例化!
  • 我不是语言专家,但我阅读 [class.copy]/p9 的方式是,在此示例中,编译器生成的 A 的复制构造函数具有签名 A(const A&amp;)。因此,在此示例中与模板化 A(T&amp;) 构造函数的匹配较差(由于 [over.match] 中的规则,我目前懒得缩小到更具体的部分)。
  • @Lightness:不,它没有。在这种情况下,默认复制 ctor 采用 A const&amp; 参数,我们有一个非 const 左值参数,因此,T&amp; 构造函数,实例化为 A&amp;,获胜。
  • 如果像你们这样的两位专家不能就标准的内容达成一致,在我看来,这强烈表明存在需要澄清的标准问题。请联系open-std.org/jtc1/sc22/wg21/docs/cwg_active.html的作者帮助我们澄清这个问题。
猜你喜欢
  • 2015-07-18
  • 1970-01-01
  • 2019-03-08
  • 1970-01-01
  • 2021-07-21
  • 2014-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多