强制 C++ 为参数分配新地址

Force C++ to assign new addresses to arguments

似乎当我将不同的整数直接传递给一个函数时,C++ 会为它们分配相同的地址,而不是将不同的地址分配给不同的值。这是设计使然,还是可以关闭的优化?请参阅下面的代码以获取说明。

#include <iostream>

const int *funct(const int &x) { return &x; }

int main() {

  int a = 3, b = 4;
  // different addresses
  std::cout << funct(a) << std::endl;
  std::cout << funct(b) << std::endl;

  // same address
  std::cout << funct(3) << std::endl;
  std::cout << funct(4) << std::endl;
}

这个问题的更大背景是我正在尝试构建一个指向整数的指针列表,我将逐个添加(类似于 funct(3))。由于我无法修改方法定义(类似于funct的),我想存储每个参数的地址,但它们最终都具有相同的地址。

函数 const int *funct(const int &x) 接收绑定到 int 变量的引用。

abint 变量,所以 x 可以绑定到它们,它们将有不同的内存地址。

由于该函数接受 const 引用,这意味着编译器还将允许 x 绑定到 temporary int 变量(而 非常量 引用不能绑定到临时变量)。

当您将数字文字传递给 x 时,如 funct(3),编译器会创建一个 temporary int 变量来保存字面值。 temporary 变量仅在进行函数调用的语句的生命周期内有效,然后临时变量超出范围并被销毁。

因此,当您在 separate 语句中对 funct() 进行 多次 调用时,编译器可以自由重用这些临时变量的内存相同,例如:

// same address
std::cout << funct(3) << std::endl;
std::cout << funct(4) << std::endl;

实际上等同于:

// same address
int temp;
{
temp = 3;
std::cout << funct(temp) << std::endl;
}
{
temp = 4;
std::cout << funct(temp) << std::endl;
}

但是,如果您在 单个 语句中对 funct() 进行 多次 调用,编译器将被迫进行单独的临时变量,例如:

// different addresses
std::cout << funct(3) << std::endl << funct(4) << std::endl;

实际上等同于:

// different addresses
{
int temp1 = 3;
int temp2 = 4;
std::cout << funct(temp1) << std::endl << funct(temp2) << std::endl;
}

Demo

函数

const int *funct(const int &x) { return &x; }

将 return 任何 x 引用的地址。

因此,如您所料,这将打印 a:

的地址
std::cout << funct(a) << std::endl;

表达式funct(3)的问题是无法引用常量并将其作为参数传递。常量没有地址,因此出于实际原因,C++ 不支持引用常量。 C++ 实际上支持的是制作一个临时对象,用值 3 初始化它,并引用 that 对象。

基本上,在这种情况下,编译器将翻译为:

std::cout << funct(3) << std::endl;

变成等同于此的东西:

{
  int tmp = 3;
  std::cout << funct(tmp) << std::endl;
}

除非你做一些事情来延长临时对象的生命周期,否则它会在函数调用后超出范围(或者就在下一个序列点之前,我不确定)。

由于 3 创建的临时文件在您从 4 创建临时文件之前超出范围,第一个临时文件使用的内存可能会重新用于第二个临时文件。