当我在 C++ 中将派生类的指针分配给指针时,地址会更改
address changes when i assign to a pointer a pointer from a derived class in C++
我是C++的新手,我正在试验多态性。我有以下代码:
#include <iostream>
class Base1
{
protected:
int b1;
public:
int m() { return 1; }
};
class Base2
{
protected:
int b2;
public:
int n() { return 2; }
};
class Der : public Base1, public Base2
{
protected:
int d1;
public:
int m() { return 11; }
int n() { return 21; }
};
int main()
{
Der *ptr = new Der();
Base1 *b1 = ptr;
Base2 *b2 = ptr;
std::cout << "d: " << ptr << ", m: " << ptr->m() << ", n: " << ptr->n() << "n";
std::cout << "b1: " << b1 << ", m: " << b1->m() << "n";
std::cout << "b2: " << b2 << ", n: " << b2->n() << "n";
delete ptr;
return 0;
}
当我运行这段代码时,有趣的是 b2 移动了 4 个字节,这是我的输出:
d: 0x564eab6cbeb0, m: 11, n: 21
b1: 0x564eab6cbeb0, m: 1
b2: 0x564eab6cbeb4, n: 2
为什么这种情况只发生在 b2 上?我想这与事物在内存中的存储方式有关,因为如果我删除 b1 中的 int 字段,b2 不会受到影响。有没有办法轻松查看堆叠和堆?我想看看会发生什么。(我正在使用虚拟工作室代码(
OP 的样本(简化一点(
struct Base1 {
int b1;
};
struct Base2 {
int b2;
};
struct Der: Base1, Base2 { };
可能会导致以下内存布局:
// start of Der
// start of Base1
0000: Base1::b1 // type int
// start of Base2
0004: Base2::b2 // type int
因此,当实例化struct Der
时,其内容的一部分是struct Base2
的实例,但它不会从Der
实例的同一地址开始。
跟
Der *ptr = new Der();
初始化
Base2 *b2 = ptr;
不会导致地址的纯副本ptr
到b2
.还有一个从Der*
到Base2*
的隐式转换。编译器知道类Der
和Base2
的关系。因此,转换会导致Base2
偏移量在Der
中静默添加。
为了在实际中展示这一点,我做了一个小演示。(我不确定它有多令人信服。
#include <iostream>
struct Base1 {
int b1 = 1;
};
struct Base2 {
int b2 = 2;
};
struct Der: Base1, Base2 { };
int main()
{
Der *ptr = new Der;
Base2 *b2;
std::cout << "ptr:" << ptr << ", ptr1->b2: " << ptr->b2 << 'n';
b2 = ptr;
std::cout << "b2: " << b2 << ", b2->b2: " << b2->b2 << 'n';
}
使用 gcc 4.1.2 编译,您可以在实际分配发生的地方找到以下代码:
mov %rax, QWORD PTR [%rbp-24] # %rbp-24 <- storage of ptr on stack
add %rax, 4
mov QWORD PTR [%rbp-32], %rax # %rbp-32 <- storage of b2 on stack
编译器资源管理器上的实时演示
注意:
使用大多数现代编译器版本进行编译将发出类似的add
命令,但也发出许多其他东西,这些东西不像旧版本的生成代码那样容易破译(通过眼睛(。因此,我选择了我能找到的最古老的gcc
。
是的,它与事物在内存中的存储方式有关。
类Der
包括作为子对象的Base1
和Base2
。
看这derived_class。
相关文章:
- 将指针分配给另一个指针时会发生什么情况?
- C++将一个指针分配给另一个指针时执行的类型检查
- 我似乎无法为指针分配一个数组,然后更改数组的内容
- C++为 void 指针分配一个字符串
- 当我在 C++ 中将派生类的指针分配给指针时,地址会更改
- MPI 集合通信中的指针分配
- 函数指针分配在创建 DLL 后导致错误
- 通过双指针分配指针
- C++编译时使用 constexpr 字符数组指针分配静态数组?
- 我可以直接为指针分配地址吗?如果是,如何做到这一点
- 为什么为char指针分配内存不会截断char序列
- C++指针分配字符数组的地址
- 将 void 指针分配给另一个 void 指针
- 如何将不同的成员函数指针分配给注册类的不同实例?
- 如何为指针分配特定的内存地址?
- C++ - 无法将顶部常量指针分配给另一个非常量指针
- 将指针分配给另一个指针时会发生什么情况?
- 为指向C++中的对象/对象的指针分配堆内存
- 将指针分配给字符串变量中包含的地址
- 当直接分配时,为什么此功能指针分配起作用,而不是与有条件的操作员一起使用