强制 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
变量的引用。
a
和 b
是 int
变量,所以 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;
}
函数
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
创建临时文件之前超出范围,第一个临时文件使用的内存可能会重新用于第二个临时文件。
似乎当我将不同的整数直接传递给一个函数时,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
变量的引用。
a
和 b
是 int
变量,所以 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;
}
函数
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
创建临时文件之前超出范围,第一个临时文件使用的内存可能会重新用于第二个临时文件。