【问题标题】:Why the standard does not allow to pass temporaries by non-const reference? [duplicate]为什么标准不允许通过非常量引用传递临时变量? [复制]
【发布时间】:2014-12-13 22:50:04
【问题描述】:

我已经阅读了很多关于标准如何不允许通过非常量引用传递临时变量的信息,但我可以找到任何令人信服的原因。

我遇到的常见论点是它不安全,因为值的生命周期是未知的。但实际上它不是,它绑定到它的参数的函数,并且将保持“活动”直到该函数返回,因此在该函数内部使用它是安全的,将它传递给它内部的另一个函数和另一个... 基本上只要都是同步执行,应该是安全的,因为对象会一直留在那里,直到第一个接收它的函数返回。

这两种方法的根本区别是什么?

doSomething(createSomething());

{
    something s = createSomething();
    doSomething(s);
}

除了第二个不必要地使用您将只使用一次的对象的标识符污染范围。

在我看来,它是临时的,它只是限制了造成损害的可能性,因为在该函数调用之后将不再使用它。

有人可以通过引用传递一个临时的来提供一个片段,说明在实践中可能会发生什么样的坏事?

另外,我的问题严格来说是 c++11 之前的,所以右值引用超出了它的范围。

编辑:从链接的问题,sbi 的回答:

// this doesn't compile: 
g(getx()); // g() would modify an object without anyone being able to observe

但这意味着人们通过引用传递某些东西的唯一原因是能够在该函数返回后观察该函数中所做的更改。现在,显然,如果您使用临时的,不用说这不是您的意图的一部分,也不是刚刚提到的原因是通过引用传递的唯一原因。这就是为什么该问题的范围与标记为重复的问题不同的原因。您很可能通过引用传递以避免昂贵的复制,并且您的设计可能涉及使用完全封装在该函数中的对象以及在其中调用的函数。

另一个问题侧重于通过引用传递的一种用法,并没有解释可能出现的问题,也没有考虑到使用临时否定一个关注答案地址的事实。它基本上回答了“因为它会在没有任何人能够观察的情况下修改对象”,这被正确地呈现为毫无意义,但当您首先使用临时对象时,这显然不是意图。

换句话说,答案是“你做不到,因为当你不想观察变化时,你无法观察到变化”...... DO'H 怎么会有限制是无法做你显然不想做的事情吗?

【问题讨论】:

  • 在深入研究原因之前,值得一提的是,在 c++11 及更高版本中,您可以将 r 值引用传递给非常量临时变量。
  • @remyabel - 我看到了,它没有回答我的问题。
  • 正如(简要)在对链接问题的回答中描述的那样,非常量参考参数是 outin-out 参数。这意味着您在临时传递时丢失信息。此外,编译器可以创建临时文件。 Stroustrup 使用像void foo(int&); double x = 41; foo(x); 这样的示例(D&E、TC++PL),其中将创建一个临时对象并将其绑定到引用参数。变量x 没有被修改,令人惊讶。
  • @user3735658 这是同一个问题;如果现有答案不足,则应针对现有问题提出任何新答案
  • @dyp - 好吧,我不会说令人惊讶,只是有些人并不总是意识到的隐式转换。

标签: c++ pass-by-reference temporary


【解决方案1】:

原因是 Stroustrup 先生推断传递对可变临时的引用很可能是编程错误的结果 - 因为在函数调用之后无法访问临时中的任何计算结果。

示例:

struct foo {...};

func(foo());
// the foo has already been destroyed here, so any modified state is inaccessible.

公平地说,尽管自 r 值引用的发展以来这看起来是短视的,但他的推理是合理的。虽然它可能需要多行代码,但总有一种方法可以达到相同的效果。

例子:

{
  foo f;
  func(f);
}

foo_func();

地点:

void foo_func() {
  foo f;
  func(f);
}

这是我看到的示例的重新引用,它是您无法在函数调用中将可变临时绑定到左值的原因。这个错误很微妙,但很严重,很难找到:

void inc(int& arg) { arg++; }

typedef long MyInt;

int main() {
  MyInt i = 0;
  inc(i);  // <<-- HINT: implicit conversion from long to int creates a temporary COPY, not reference
  if (i == 1) {
     // Life-saving logic
  }
}

来源:comp.lang.c++.moderated

【讨论】:

  • 但是您可以在该函数调用中访问和使用它数百万次。它可能很容易满足您的所有需求:)
  • 我没说他是对的 :-)
  • 所以 Stroustrup 先生认为通过引用传递的唯一原因是修改某些内容并在函数返回后继续使用它?听起来不是很好。
  • 好吧,我想要制作一门通用、高效且最重要的语言需要 20 年的发展 - 允许您编写除非逻辑正确否则无法编译的程序。 :-)
  • ... 或者是不必要的臃肿和过于复杂,几乎没有从之前的设计失误中吸取教训,并要求人们放弃逻辑、理性和理智以符合其古怪之处:)
猜你喜欢
  • 2013-08-22
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 2021-08-10
  • 2019-05-10
  • 2017-07-08
相关资源
最近更新 更多