我读过Answers to C++ interview questions,其中有一个让我困惑:
问:C ++编译器何时创建临时变量?
答:假设函数参数是“const引用”,编译器会以下列两种方式生成临时变量。
a)实际参数是正确的类型,但它不是Lvalue
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参数?
答案 0 :(得分:7)
我认为这里没有任何自相矛盾的地方。如果参数不是左值,或者类型错误,则由于显而易见的原因,引用不能直接附加到参数;因此需要一个正确类型的中间临时。该引用附加到该临时值。
Cube
函数确实被破坏(格式错误),因为它试图修改const
值。
答案 1 :(得分:3)
我看错了 - 而且gcc会产生错误:
const_ref.cpp: In function ‘double cube(const double&)’:
const_ref.cpp:3: error: assignment of read-only reference ‘num’
答案 2 :(得分:2)
编译器可以生成临时变量。它没有。
是的,Cube
实际上不应该编译。
答案 3 :(得分:1)
您可以将表达式的结果(包括隐式转换的结果)传递给引用到const。理由是虽然使用(const X & value)
可能更便宜,但取决于类型X的复制成本,而不是(X value)
,效果几乎相同; value
被使用但未被修改(除非有一些冒险的常量)。因此,允许创建临时对象并将其传递给函数是无害的。
你不允许使用指针指向const或引用指向非const指令,因为可能会发生意外(和坏)事情,例如你可能期望将长时间强制转换为long,这不会发生。
你对num = num * num * num;
无效是正确的。这是文本中的一个错误,但它所提出的论点仍然存在。
答案 4 :(得分:0)
因为在这两个示例中,没有正确类型的非临时对象。
答案 5 :(得分:0)
我相信你对函数多维数据集无法编译是正确的。无论如何,这应该失败,它确实在我的编译器(VC ++ 2008)上。
至于创建一个临时的:
只要实际参数:
,就会创建一个支持const引用的临时值i)不是参考的正确类型, ii)可以隐式转换为正确的类型。
在示例a)中,您的问题会创建一个临时double
来保存值3.0 + temp
。然后使用Cube()
对临时的引用调用const
。这是因为你不能引用3.0 + temp
,因为它不是一个变量(它是一个rvalue - 一个表达式的结果),所以它没有内存地址,也不能支持参考。隐式地,编译器将创建一个临时double
,然后为其赋值3.0 + temp
。
在您的示例b)中,您有long
,但您的功能需要double
。编译器将隐式地将long
转换为double
。它通过创建临时double
,为其分配转换后的temp
值,然后创建对const
的临时引用,并将该引用传递给cuberoot
<来实现此目的/ p>
答案 6 :(得分:0)
是。正如你在这里展示的那样,Cube()应该无法编译。