0

就在我以为我能很好地掌握指针的时候,我又感到困惑了。您的见解可能会有所帮助。

我想我可以用非常笼统的术语来说明让我感到困惑的地方,例如:

a) 如果我写A* p = new A();(A某个类在哪里),然后做类似的事情(*p).do_stuff(),那么指向的对象p可能会在内存中移动,那么为什么还要p指向我的对象呢?

b) 类和类的成员变量如何存储在内存中。

但也许我更具体地告诉你我遇到的问题更有用。假设我有一个Car具有成员变量的类Engine engine_;Engine其他类在哪里)。美好的。现在假设由于某种原因我想创建一个类,该类有一个成员变量,该成员变量是指向 a 的指针Engine,例如:

class Car
{
    friend Repair;
public:
    Car() {engine_ = Engine();}
private:
    Engine engine_;
};

class Repair
{
public:
    Repair(const Car &car) : engine_(&(car.engine_)) {}
private:
    Engine *engine_;
};

没有机会repair.engine_总是指向我汽车的引擎,有吗(?)但即使在第二个版本中:

class Car
{
    friend Repair;
public:
    Car() {engine_ = new Engine();}
    ~Car() {delete engine_;}
private:
    Engine *engine_;
};
// Maybe I need/should write consts somewhere, not sure

class Repair
{
public:
    Repair(const Car &car) : engine_(car.engine_) {}
private:
    Engine *engine_;
};

尽管这似乎更有可能奏效,但我不知道/理解它是否会......

提前感谢您的回答!

4

4 回答 4

2

如果我写A* p = new A();A某个类在哪里),然后做类似的事情(*p).do_stuff(),那么 p 指向的对象可能会在内存中移动

不,不会的。(至少,*p会保持原样;如果它本身有指针成员,那么那些可能会被重置以指向其他地方。)

类和类的成员变量如何存储在内存中

作为位。

class Foo {
    int i;
    char *p;

  public:
     void bla();
};

将表示为int(可能是 32)的位,然后是指针(32 或 64)的位,中间可能有一些填充。该方法不会占用您的实例中的空间,它是单独存储的。

至于你的例子,我并不完全理解这个问题。如果对象还活着,它应该可以工作,并且只要对象Car还活着,它就不会重置它。(不过,它看起来并不特别健壮。)Engine*Repair

于 2012-06-27T18:02:50.857 回答
0

在情况 1) 和情况 2) 中,不能保证repair.engine_始终指向您的汽车,因为它是朋友类而不是“汽车”类的成员

于 2012-06-27T18:08:10.763 回答
0

正如其他人所说,当您执行诸如(*p).do_stuff();. 你一定误解了你在某个时候学到的东西。

对于您的第二个问题,成员函数和成员变量存储在内存中的不同位置。成员函数的代码只为每个类生成一次,而不是为类的每个实例生成一次。此代码存储在内存中的某个位置。

至于成员变量,这就是人们在提到您的对象在内存中的位置时所谈论的内容。例如,如果你有一个像

class MyClass{
  private:
    int a;
    int b;
    double c;
  public:
    void fun();
};

我们假设它的一个实例存储在内存位置 0x0000,这意味着它a位于位置 0x0000,b 位于 0x0004,c 位于 0x0008(或类似的东西,取决于内存的布局方式)。该函数fun()完全存储在其他地方。

现在如果我们创建另一个实例MyClass,它的a变量可能在 0x000C,它b可能在 0x0010,它c在 0x0014。最后,它与第一个实例fun()的位置完全相同fun()

于 2012-06-27T18:10:50.307 回答
0

C++ 中分配的指针new不会移动。您可能会想到malloc,其中可以realloc'd 指针并因此可能会转到新位置。

Bjarne Stroustrup 认为 C++ 容器通常提供了一种更好的方式来处理希望拥有动态大小的内存:

http://www2.research.att.com/~bs/bs_faq2.html#renew

为了允许内存的移动和重组,一些系统使用抽象句柄,这些句柄需要锁定到指针中才能使用它们……例如 Windows:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366584(v=vs.85).aspx

在需要进行某种定期内存碎片整理的系统中,使用您锁定到指针中的抽象内容可能是有意义的。但是默认情况下,C++ 不会为这种间接方式付出代价,只有在有意义的情况下才会实现它。

(不利的一面是,如果您分配一百万个对象然后删除其中的 999,999 个,则使用不可移动的指针......剩下的一个对象可能会一直坐在地址空间的顶部。操作系统/分页系统是应该比让它成为问题更聪明,但是如果您的分配器是自定义的,这可能会使您的堆变大.例如:如果您使用内存映射文件作为对象的后备存储.. .您将被一个大且大部分为空的磁盘文件所困。)

于 2012-06-27T18:12:03.753 回答