4

我是 C++ 新手,我在临时主题上苦苦挣扎。我在任何地方都找不到编译器将创建临时文件的所有情况的明确列表。实际上,几天前我想到,当我们将右值作为const 引用参数传递时,编译器将创建一个临时值并将右值放入该临时值以保存它,并将临时值作为参数传递。把这个例子给我的老师,

void func(const int& _param){}

int main()
{
  func(10);
  // int __tmp__ = 10;
  // func(__tmp__);
  return 0
}

他说在这种情况下编译器不会创建一个临时的,而是会直接优化代码,替换函数体内所有出现的 10,所以在那之后,我比以往任何时候都更加困惑。

4

3 回答 3

4

如果您指的是语言概念而不是编译器最终会做什么,那么简单来说,临时是一个最终由某个表达式产生的值,并且不绑定到任何变量。它的值通常用于一些中间计算,然后被丢弃。这是一个有点做作的例子。

std::string x = "foo";
std::string y = "bar";

auto length = (x + std::to_string(some_number) + y).size();
// __TEMP0__       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
// __TEMP1__   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// __TEMP2__  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

的结果在std::to_string(some_number)使用时没有分配给任何东西,所以它只是暂时的。它在 [sub]expression 中使用x + std::to_string(some_number),它创建另一个临时字符串,它本身与+'d 一起创建另一个临时字符串,y其大小被占用并分配给length。在这种情况下,所有涉及的临时变量都将存在0直到整个表达式的求值结束,然后被丢弃。就好像代码是这样的。

std::string x = "foo";
std::string y = "bar";

std::string __TEMP0__ = std::to_string(some_number);
std::string __TEMP1__ = x + __TEMP0__;
std::string __TEMP2__ = __TEMP1__ + y;

auto length = __TEMP2__.size();

除了临时变量保留为右值并将在评估后被销毁__TEMP2__.size()


0好吧,就好像它们存在一样。谁知道你的编译器会做什么来优化它。

于 2022-02-02T18:34:08.903 回答
3

“as-if”规则在这里适用。请参阅https://en.cppreference.com/w/cpp/language/as_if

您的工作是通过编写一些 C++ 源代码来指定您的意图。编译器的工作是将其转换为符合意图的机器代码。

C++ 标准中没有任何内容可以告诉您在程序中创建了多少临时对象。一个好的编译器会优化你的程序

int main(){}

如果临时的创建具有可观察到的副作用,那么编译器的选项会受到更多限制。但在 NRVO 和 RVO 情况下,可以忽略这一点。在后来的 C++ 标准中,它是必需的。

于 2022-02-02T18:03:24.490 回答
1

而是直接优化在函数体内所有出现的替换 10 的代码

是否(以及如何)优化它或其他任何东西都取决于编译器。除了某些例外(例如复制省略),当且仅当优化不影响可观察行为(另一个答案中提到的“as-if rule”)时,才允许优化。

当我们将右值作为 const 引用参数传递时,编译器将创建一个临时值并将右值放入该临时值以保存它,将临时值作为参数传递

取决于右值的类型。10 是一个纯右值,它甚至不是从 C++17 开始的对象。引用不能直接绑定到纯右值,所以它首先被具体化为一个 xvalue,这是一个临时的

如果您传递了一个 xvalue,则引用将直接绑定到它。

以上适用于C ++ 17,我不确定以前是如何工作的。

于 2022-02-02T18:25:47.580 回答