2

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

如果这是我应该了解的事情,我该如何进行检查?

IE

int j = 0;
double k = 2.2;
double* p = &k;

如果 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
}
4

4 回答 4

6

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

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

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

例如,这个:

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

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

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

对象的生命周期是程序执行期间保证为其保留存储的部分。一个对象存在,有一个不变的地址,并在其整个生命周期中保留其最后存储的值。

带有(非规范性)脚注:

术语“恒定地址”意味着在可能不同时间构造的指向对象的两个指针将比较相等。在同一程序的两次不同执行期间,地址可能不同。

我在 C++ 标准中没有找到类似的明确声明;要么我错过了它,要么作者认为它太明显而无法说明。

于 2013-04-09T23:20:07.767 回答
1

编译器可以随意做任何事情,只要它不影响可观察的程序行为。

首先,考虑到局部变量甚至可能不会被放入内存(它们可能只存储在寄存器中,或者完全优化掉)。

因此,即使在您获取局部变量地址的示例中,这并不意味着它必须位于内存中的固定位置。这取决于你继续用它做什么,以及编译器是否足够聪明来优化它。例如,这个:

double k = 2.2;
double *p = &k;
*p = 3.3;

可能相当于:

double k = 3.3;
于 2013-04-09T23:16:08.720 回答
1

是和不是。

全局变量将保留在同一个位置。

每次调用和返回函数时,堆栈变量(在函数内部)都会被分配和释放。例如:

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

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

于 2013-04-09T23:19:29.183 回答
0

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

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