【问题标题】:Referencing the same variable that you're declaring引用您声明的相同变量
【发布时间】:2011-12-04 19:44:56
【问题描述】:

在使用 C++ 代码时,我曾多次看到以下类型错误:

QString str = str.toUpper();

这可能是一个相当容易犯的错误,但它可以编译和执行(有时会崩溃,有时不会)。我看不出在任何情况下这会是你真正想做的事情。

一些测试表明,复制构造函数被调用,而不是默认的,并且对象是从复制构造函数中获得的。

谁能解释为什么这不是编译器错误,甚至不是警告?

【问题讨论】:

  • 这被指定为未定义的行为(不需要诊断),可能是因为此类代码的一个或多个实例的诊断过于复杂。
  • 可能是因为编译器不知道 toUpper() 返回相同的实例?我可以想象编译器编写者很难检查这一点。
  • @MarkB:这是已定义的行为,请参阅我的回答。

标签: c++ construction


【解决方案1】:

从技术上讲,对象str 是在您到达等号时定义的,因此可以在该点使用它。

错误在于尝试使用自身初始化对象,并且允许编译器对此发出警告(如果它能够检测到它)。但是,由于并非在所有情况下都可以进行检测,因此不需要编译器。

例如,如果int f(const int&) 不使用其参数的值,则int x = f(x); 是完全正确的。如果还没有看到函数体,编译器怎么知道呢?

【讨论】:

  • 这是有道理的。我想我会争辩(为了理智,如果没有别的)在尚未构建的 x 上调用 f(x) 仍然应该是一个错误,因为正如你提到的那样,唯一安全的情况是一个函数不使用它。
  • 嗯,是的,但是函数可以写入到它,这对于内置类型实际上是可以的。
  • 值得注意的是,当通过auto 关键字定义对象时,特别禁止这种语法,但出于类型推断的原因。 auto x = x + 1; 无效,兼容的编译器应该拒绝它。
  • @Chris - 它实际上可以保存一个指针或对对象的引用,然后稍后使用它。它只是不能使用该值(因为还没有)。 C 和 C++ 以不禁止仅远程有用的东西而闻名。
  • 那么等号处x的状态究竟是什么?此时调用了哪个构造函数?
【解决方案2】:

没有错误或警告,因为它相当于:

QString str;
str = str.toUpper();

就像

QString str = "aaa";

相同
QString str;
str = "aaa";

要在同一语句中执行此操作,您需要使用无法编译的构造函数:

QString str(str.toUpper());

就像:

QString str("aaa");

不等于

QString str;
str = "aaa";

【讨论】:

  • 绝对不等同于QString str; str = str.toUpper(); 就像QString str = "aaa"; 不调用赋值运算符一样。
  • QString str = "aaa";QString str; std = "aaa" 真的一样吗?我不是 C++ 专家,但在我看来,第一个调用构造函数,第二个调用默认构造函数,然后 operator=Codepad 似乎同意。
  • -1: QString str = "aaa" 不会调用默认构造函数。它将调用采用const char* 的构造函数,该构造函数的参数将是"aaa"。也就是说,它与默认构造QString然后复制分配给它相同。
  • @NicolBolas:它还会调用复制构造函数。可以省略该调用,但是,语法 QString str = "aaa" 需要一个可访问的复制构造函数,无论实际调用是否被省略
猜你喜欢
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多