c++ - 以自身为引用构造对象?

标签 c++ copy-constructor

我刚刚意识到这个程序可以编译和运行(gcc 版本 4.4.5/Ubuntu):

#include <iostream>
using namespace std;

class Test
{
public:
  // copyconstructor
  Test(const Test& other);
};

Test::Test(const Test& other)
{
  if (this == &other)
    cout << "copying myself" << endl;
  else
    cout << "copying something else" << endl;
}

int main(int argv, char** argc)
{
  Test a(a);              // compiles, runs and prints "copying myself"
  Test *b = new Test(*b); // compiles, runs and prints "copying something else"
}

我不知道为什么这甚至可以编译。我假设(就像在 Java 中一样)在调用方法/构造函数之前评估参数,所以我怀疑这种情况必须由语言规范中的某些“特殊情况”涵盖?

问题:

  1. 有人可以解释一下吗(最好是引用规范)?
  2. 允许这样做的理由是什么?
  3. 它是标准 C++ 还是特定于 gcc 的?

编辑 1:我刚刚意识到我什至可以写 int i = i;

编辑 2:即使使用 -Wall-pedantic,编译器也不会提示 Test a(a);

编辑 3:如果我添加一个方法

Test method(Test& t)
{
  cout << "in some" << endl;
  return t;
}

我什至可以在没有任何警告的情况下执行 Test a(method(a));

最佳答案

这个“被允许”的原因是因为规则说标识符范围在标识符之后立即开始。在这种情况下

int i = i;

RHS i 在 LHS i“之后”,所以 i 在范围内。这并不总是坏事:

void *p = (void*)&p; // p contains its own address

因为可以在不使用变量值的情况下对变量进行寻址。在 OP 的复制构造函数的情况下,不会轻易给出错误,因为绑定(bind)对变量的引用不需要初始化变量:它等同于获取变量的地址。合法的构造函数可以是:

struct List { List *next; List(List &n) { next = &n; } };

你看到的参数只是被处理,它的值没有被使用。在这种情况下,自引用实际上是有意义的:列表的尾部由自引用给出。实际上,如果您将“next”的类型更改为引用,则别无选择,因为您不能像对指针那样轻松地使用 NULL。

像往常一样,问题是倒退的。问题不是为什么变量的初始化可以引用自身,问题是为什么它不能向前引用。 [在 Felix 中,这是可能的]。特别是,对于与变量相反的类型,缺乏转发引用的能力是非常糟糕的,因为它阻止了递归类型的定义,而不是通过使用不完整的类型,这在 C 中就足够了,但在 C++ 中就不够了,因为存在模板。

关于c++ - 以自身为引用构造对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4368361/

相关文章:

c++ - 如何使用 C++ 库找出 HDF5 中数据集的 PredType

c++ - 'int i = 0' vs. ' int i(0 )' in a ' for' 循环(赋值 vs 初始​​化计数变量)

c++ - 为什么以下默认复制语法在 C++ 中无效?

c++ - 如何在具有指向对象的指针数组的类中创建复制构造函数和析构函数,其中对象本身具有指向 int 的指针数组

c++ - 在 unique_ptr 中显式调用对象的复制构造函数

c++ - 使用 using 声明时,非限定名称查找如何工作?

c++ - 在交互式程序中使用带有 cout 和 stringstream 的预处理器指令 - C++

c++ - 覆盖boost中的验证方法不适用于样式集

c++ - 存在用户定义的移动构造函数/赋值时的隐式复制构造函数

c++ - 无法理解编译器在复制构造函数上引发的错误消息