C/C++:在程序的持续时间内,内置对象如`int``double`总是保留在内存中的确切位置?

woo*_*sah 2 c++ memory types built-in

没有动态定义的内置类型,在程序持续期间始终保持在同一块内存中吗?

如果这是我应该了解的,我该如何去检查它?

int j = 0;
double k = 2.2;
double* p = &k;
Run Code Online (Sandbox Code Playgroud)

如果C/C++程序是高度内存密集型的,那么系统架构或编译器是否会移动所有这些对象?

注意:我不是在谈论诸如此类的容器std::vectors<T>.在某些情况下,这些显然可以重新分配,但这又是动态的.


附带问题: 以下情况显然会引起一些人的注意.举个例子,这个指针在程序的持续时间内是否总是有效的?

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

struct null_deleter
{
    void operator() (void const *) const {};
};

int main()
{
    // define object
    double b=0;

    // define shared pointer
    std::shared_ptr<double> ptr_store;
    ptr_store.reset(&b,null_deleter()); // this works and behaves how you would expect
}
Run Code Online (Sandbox Code Playgroud)

Kei*_*son 6

在抽象机器中,对象的地址在该对象的生命周期内不会改变.

(这里的"对象"一词并不是指"面向对象"的东西;"对象"只是存储的一个区域.)

这实际上意味着程序必须表现得好像对象的地址永远不会改变.编译器可以生成播放它喜欢的任何游戏的代码,包括移动对象或者根本不存储它们,只要这些游戏不会以违反标准的方式影响可见行为.

例如,这个:

int n;
int *addr1 = &n;
int *addr2 = &n;
if (addr1 == addr2) {
    std::cout << "Equal\n";
}
Run Code Online (Sandbox Code Playgroud)

必须打印"Equal" - 但是一个聪明的优化编译器可以合法地消除除输出语句之外的所有内容.

ISO C标准在第6.2.4节中明确说明了这一点:

对象的生命周期是程序执行的一部分,在此期间保证为其保留存储.存在一个对象,具有一个常量地址,并在其整个生命周期内保留其最后存储的值.

(非规范性)脚注:

术语"常量地址"意味着在可能不同时间构造的对象的两个指针将比较相等.在同一程序的两次不同执行期间,地址可能不同.

我没有在C++标准中找到类似的显式语句; 或者我错过了,或者作者认为太明显无法说明.