Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C/C++;:在程序运行期间,诸如'int``double`之类的内置对象是否始终保持在内存中的确切位置?_C++_Memory_Types_Built In - Fatal编程技术网

C++ C/C++;:在程序运行期间,诸如'int``double`之类的内置对象是否始终保持在内存中的确切位置?

C++ C/C++;:在程序运行期间,诸如'int``double`之类的内置对象是否始终保持在内存中的确切位置?,c++,memory,types,built-in,C++,Memory,Types,Built In,不是动态定义的内置类型在程序执行期间是否始终保留在同一块内存中 如果这是我应该了解的事情,我该如何着手检查 i、 e 如果一个C/C++程序(比如)是高度内存密集型的,那么系统架构或编译器是否会绕过所有这些对象 注意:我不是在谈论容器,比如std::vectors。在某些情况下,这些显然可以重新分配,但这也是动态的 附带问题: 下面的场景显然会引起一些关注。举个例子,这个指针在程序运行期间是否始终有效 由于我的无知,这个附带问题已经过时了 struct null\u deleter { voi

不是动态定义的内置类型在程序执行期间是否始终保留在同一块内存中

如果这是我应该了解的事情,我该如何着手检查

i、 e

如果一个C/C++程序(比如)是高度内存密集型的,那么系统架构或编译器是否会绕过所有这些对象

注意:我不是在谈论容器,比如
std::vectors
。在某些情况下,这些显然可以重新分配,但这也是动态的


附带问题: 下面的场景显然会引起一些关注。举个例子,这个指针在程序运行期间是否始终有效

由于我的无知,这个附带问题已经过时了

struct null\u deleter
{
void运算符()(void const*)const{};
};
int main()
{
//定义对象
双b=0;
//定义共享指针
std::共享存储;
ptr_store.reset(&b,null_deleter());//它的工作方式和行为方式与您预期的相同
}

只要不影响可观察到的程序行为,编译器可以自由地执行任何它想做的事情

首先,考虑局部变量可能不被放入内存中(它们可能只存储在寄存器中,或者完全被优化)。 因此,即使在您的示例中,您获取了一个局部变量的地址,但这并不意味着它必须位于内存中的固定位置。这取决于你要用它做什么,以及编译器是否足够聪明来优化它。例如,这:

double k = 2.2;
double *p = &k;
*p = 3.3;
int n;
int *addr1 = &n;
int *addr2 = &n;
if (addr1 == addr2) {
    std::cout << "Equal\n";
}
可能相当于:

double k = 3.3;
是和否

全局变量将保持在同一位置

每次调用并返回函数时,堆栈变量(函数内部)都将被分配和解除分配。例如:

void k(int);
void f() {
    int x;
    k(x);
}
void g() {
    f();
}
int main() {
    f();
    g();
}

在这里,第二次调用
f()
,它的
x
将位于不同的位置。

在抽象机器中,对象的地址在该对象的生存期内不会更改

(这里的“对象”一词并不是指“面向对象”的任何东西;“对象”只是一个存储区域。)

这确实意味着一个程序的行为必须像一个对象的地址永远不变一样。编译器可以生成可以玩任何它喜欢的游戏的代码,包括移动对象或根本不将它们存储在任何地方,只要这些游戏不会以违反标准的方式影响可见行为

例如,这:

double k = 2.2;
double *p = &k;
*p = 3.3;
int n;
int *addr1 = &n;
int *addr2 = &n;
if (addr1 == addr2) {
    std::cout << "Equal\n";
}
intn;
int*addr1=&n;
int*addr2=&n;
如果(addr1==addr2){

这个问题有几个答案,取决于你没有提到的因素

  • 如果一个数据对象的地址从未被获取,那么一个合格的C程序甚至不能判断它是否有地址。它可能只存在于寄存器中,或者被完全优化;如果它确实存在于内存中,它不需要有一个固定的地址
  • 具有“自动”存储持续时间的数据对象(对于第一近似值,函数局部变量未使用
    静态
    声明)每次调用它们的包含函数并在其退出时销毁时都会创建它们;在任何给定时间都可能有多个副本,并且不能保证一个实例的新实例与旧实例具有相同的地址
  • 我们将
    &
    运算符称为“获取数据对象的地址”,但从技术上讲,它不是这样做的。它构造指向该数据对象的指针。指针在C标准中是不透明的实体。如果检查位(通过转换为整数)结果是实现定义的。如果在一行中检查两次位,就不能保证得到相同的数字!假设的垃圾收集C实现可以跟踪每个数据的所有指针,并在移动堆时根据需要更新它们。(人们实际上已经尝试过了。它往往会破坏那些不遵守规则的程序。)

是的,他们保证会留在原地。我希望我能有一些参考资料来证明这一点。这是一件非常基本的事情,大多数人都认为这是理所当然的。如果你在那句话之后从不修改
p
,那么
p==&k
将永远是真的。这就是你好奇的吗?我不确定我是否理解你的次要问题。为了生活对于
b
&b
的e将始终以定义明确的方式计算为相同的值…@OliCharlesworth你说得完全正确。我只是非常关心
b
在内存中的重新定位。抱歉我的无知!请再次阅读下面的所有答案
f()
被调用时,您有一个名为
x
的不同对象。原始对象仍然存在,并且仍然有其原始地址。@哈尔:不一定。
x
可能根本不在内存中。我也对另一个答案感到惊讶。每个堆栈分配的变量都可以移动,这取决于当前堆栈指针(esp,在x86上)。如果在调用堆栈的不同深度调用函数,则函数中的每个局部(
auto
)变量将位于不同的位置。@RahulBanerjee:取决于此处“变量”的定义。“对象”在它们的生命周期内永远不要移动,但是一个本地名称可以引用不同的对象,每次函数调用一次。@MooingDuck:同意。我们在这里分门别类。我认为OP的问题对于这样的语义讨论来说有点太宽泛了。根据(C)标准
&
确实“生成其操作数的地址”。结果是指针类型。我的书呆子想说,在没有进一步的上下文的情况下,它实际上可能根本就等于没有代码!