【问题标题】:Inheritance protected members variables copies in memory继承受保护的成员变量在内存中复制
【发布时间】:2018-10-27 02:11:09
【问题描述】:

有人告诉我,如果我在基类包含受保护的成员变量并且子类将构造基类时进行继承,它将在内存中复制它的成员。示例:

class Animal
{
public:
    virtual std::string& sound() { return m_sound; }
    virtual void setSound(std::string& sound) { m_sound = sound; }
    virtual int age() { return m_age; }
    virtual void setAge(int age) { m_age = age; }
protected:
    Animal(std::string sound, int age) : m_sound(sound), m_age(age) { }

    int m_age;
    std::string m_sound;
};

class Dog : public Animal
{
public:
    Dog(int speed) : Animal("Waff!!", 3), m_speed(speed) {}
    virtual int speed() { return m_speed; }
    virtual void setSpeed(int speed) { m_speed = speed; }
protected:
    int m_speed;
};

所以使用上面的示例,换句话说,如果我创建一个Dog 对象,它将为 m_sound 和 m_age 分配 2 倍的内存。
这对我来说完全没有任何意义,我一直想知道为什么编译器会做这样的事情,除非我听到的信息具有误导性。
所以说我们主要创造:

Dog bulldog(5);

调试这段代码并查看这里的内存是我得到的:

我想知道在父类数据和子类数据之间的问号所在的内存区域中究竟分配了什么。

【问题讨论】:

  • 子类包含来自 all 基类的 all 成员,无论它们是publicprotected 还是 private。这些关键字仅供会员访问使用。
  • 哪个编译器?什么平台?你究竟编译了什么代码?
  • 你问带问号的区域是什么? sizeof(string) 是什么?
  • Someprogrammerdude 感谢您的确认。这正是我的想法。 einpoklum 这是我正在开发的跨平台库,所以基本上是任何编译器。 RetiredNinja 这也让我很好奇。
  • 更明智地查看您的内存窗口:ideone.com/PWblN3

标签: c++ inheritance virtual-functions memory-layout


【解决方案1】:

有人告诉我,如果我在基类包含受保护的成员变量并且子类将构造基类时进行继承,它将在内存中复制它的成员。 ...它将为m_soundm_age分配2倍内存。

不。在您的示例中,每个Dog 类型的对象仅包含int 的两个子对象和std::string 类型的一个子对象。从技术上讲,编译器可以使用比必要更多的存储空间,但没有理由这样做,并且不允许程序为同一个成员或多个 std::string 构造函数或析构函数调用使用不同的地址。

在不知道你的来源的情况下,没有什么可说的了。

在父类数据和子类数据之间问号的内存中究竟分配了什么?

详细信息取决于您的编译器和标准库,但您标识为m_agem_speed 之间的所有或大部分字节很可能属于std::string m_sound 成员子对象。也就是说,我猜如果你做了std::cout << sizeof(std::string) << "\n";,你会得到 28 或接近它。

由于 C++ 对象模型的工作方式,sizeof(std::string) 是一个常量,每个std::string 只能获得固定数量的字节,但一个字符串可以“包含”许多字符。这通常意味着std::string 有一个char* 指向动态分配内存的指针,该内存保存实际字符。它通常还需要一种方法来了解字符串的长度和动态分配的缓冲区的容量。

但正如您所注意到的,您的字符串的字符值实际上直接出现在 std::string 对象的内存中,这可能意味着您的标准库实现正在使用 Small String Optimizationstd::string 可以包含 @ 987654338@指针和长度和容量,或者直接取一定数量的字符值。 (这可以减少动态分配和释放内存的需要,如果使用得足够频繁,这可能会占用大量 CPU 时间。)std::string 还需要一些方法来了解它当前是处于指针模式还是直接存储模式,并且该信息可能在后面的字节中。

要准确解读std::string 中每个字节的含义,您需要在编译器使用的头文件中查找类模板std::basic_string 的定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-12
    • 2014-06-09
    • 2018-12-27
    • 2012-10-03
    • 2023-03-03
    • 2014-01-30
    • 2014-06-29
    • 2011-05-24
    相关资源
    最近更新 更多