【问题标题】:Doubt on a C++ interview question对 C++ 面试问题的怀疑
【发布时间】:2010-10-04 17:43:20
【问题描述】:

我读过Answers to C++ interview questions,其中有一个让我很困惑:

问:C++ 编译器什么时候创建临时变量?

A:假设函数参数是“const 引用”,编译器通过以下两种方式生成临时变量。

a) 实际参数是正确的类型,但不是左值

double Cube(const double & num)
{
  num = num * num * num;
  return num;
}

double temp = 2.0;
double value = cube(3.0 + temp); // argument is a expression and not a Lvalue

b) 实际参数的类型错误,但类型可以转换为正确的类型

 long temp = 3L;
 double value = cuberoot(temp); // long to double conversion

我的问题是一旦函数参数是const引用,为什么编译器会生成临时变量,这不是自相矛盾吗?另外,函数 Cube 是否应该因为修改了 const 参数而无法编译?

【问题讨论】:

    标签: c++ reference constants temporary


    【解决方案1】:

    我在这里没有看到任何自相矛盾的东西。如果参数不是左值,或者类型错误,则引用不能直接附加到参数上,原因很明显;因此需要正确类型的中间临时。而是将引用附加到该临时文件。

    Cube 函数确实被破坏(格式错误),因为它试图修改 const 值。

    【讨论】:

    • @Tracy:如果您将引用实现为指针然后考虑 cube(const double*),那么 Andrey 答案的真相可能看起来更明显 - 您不能只调用 cube(4),而是必须创建一个临时的double tmp = 4;,然后调用cube(&tmp);double a = 1, b = 2; cube(&(tmp = a + b)); 也是如此。为了您的方便,这几乎是编译器在幕后可以做的事情:-)。 (确实,标准没有指定引用是如何实现的,但想象一下这种最有可能/最常见的方式会很有帮助。)
    • @Tony:感谢您的方法来想象编译器可能会做什么,实际上,这对我理解生成临时变量有很大帮助
    【解决方案2】:

    在我看来是错误的 - gcc 会产生错误:

    const_ref.cpp: In function ‘double cube(const double&)’:
    const_ref.cpp:3: error: assignment of read-only reference ‘num’
    

    【讨论】:

      【解决方案3】:

      编译器可以生成一个临时变量。没必要。

      是的,Cube 实际上不应该编译。

      【讨论】:

      • 假设编译器没有内联函数,除了在堆栈的某处创建临时变量之外,它还有什么选择?
      【解决方案4】:

      您可以将表达式的结果(包括隐式转换的结果)传递给对常量的引用。理由是,虽然(const X & value) 可能比(X value) 使用起来更便宜,这取决于类型X 的复制成本,但效果几乎相同; value 被使用但未被修改(除非有一些冒险的 const 转换)。因此,允许创建临时对象并将其传递给函数是无害的。

      不允许使用指向 const 的指针或指向非 const 的引用这样做,因为可能会发生意外(和不好)的事情,例如您可能希望将 long temp 转换回 long,这不会发生。

      num = num * num * num; 无效是正确的。这是文本中的一个错误,但它提出的论点成立。

      【讨论】:

      • @Jon:感谢指针指向 const 和引用非 const 的额外限制,但你所说的“将 long temp 转换回 long”是什么意思。
      • 我的意思是,如果它是非常量的,那么你给出的第二个例子可能会改变它的双重过去。由于传递给它的值实际上不是temp,而是通过转换temp 创建的临时double,所以应该对temp 做什么?没有好的答案,一种可能性是将值重新转换为 long 并将其分配给 temp,但这是一个缩小的转换,因此结果可能出乎意料。另一个是放弃该值,但我们预计 temp 会被更改。没有好的结果,语言禁止它是明智的。
      • 嗨,乔恩:你之前的解释适用于引用非 const 的情况,至于指针指向 const 的情况,我还是不明白。这是我的问题,假设论点是指向 const 的双精度指针,我将 temp(long 类型)传递给该函数,我怎么希望 temp 被更改,如果我这样做了,为什么我指定指向 const 的指针?
      • 在这种情况下,没有自然演员可以使用
      • 谢谢,我猜这是因为没有办法将指针指向长指针转换为指针指针
      【解决方案5】:

      因为在这两个示例中,都没有正确类型的非临时对象。

      【讨论】:

      • 谢谢,我只是过于关注通过引用传递参数的权力或限制
      【解决方案6】:

      我相信您对函数立方体无法编译的看法是正确的。无论如何,这应该会失败,并且在我的编译器(VC++ 2008)上也是如此。

      至于创建临时:

      每当实际参数出现时,都会创建一个支持 const 引用的临时值:

      i) 不是正确的参考类型,并且, ii) 可以隐式转换为正确的类型。

      在您的问题的示例 a) 中,创建了一个临时的 double 来保存值 3.0 + temp。然后调用 Cube() 并使用对临时的 const 引用。这是因为你不能引用3.0 + temp,因为它不是一个变量(它是一个右值——表达式的结果),所以它没有内存地址,也不能支持引用。隐式地,编译器会创建一个临时的double,然后给它赋值3.0 + temp

      在您的示例 b) 中,您有一个 long,但您的函数需要一个 double。编译器会将long 隐式转换为double。它通过创建一个临时的double,为其分配转换后的temp 值,然后创建一个const 对临时的引用,并将该引用传递给cuberoot

      【讨论】:

        【解决方案7】:

        是的。 Cube(),正如你在这里展示的,应该编译失败。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-07
          相关资源
          最近更新 更多