关于C++内存地址的奇怪现象
strange phenomenon about C++ memory address
太疯狂了!
为了弄清楚对象在C++中是如何存储在内存中的,
我写了下面的代码来查看变量的地址。
但是事情变得更加混乱。
所以在下面我想知道
为什么 1 不同于 2 ------这是否意味着它是一个指针?但是为什么?
为什么 1 与 3 不同 ------ 它是通过引用传递的,它们应该相同?!
#include <iostream>
#include <vector>
using namespace std;
class A {
public:
A(int age, string name) : age_(age), name_(name){};
void SetAge(int age) {
age_ = age;
}
int age_;
string name_;
};
void insert(vector<A>& p) {//passed by reference
A a1{1, "tom"};
printf(" p: %p\n", p); // p: 0x7ffc6cc98080 ------------3
printf("&p: %p\n", &p);//&p: 0x7ffc6cc981a0 ------------4
printf("&a1: %p\n", &a1); // &a1: 0x7ffc6cc980c0 /on stack, that's no problem
p.push_back(a1);
printf("&p[0]: %p\n", &p[0]); // &p[0]: 0x55b54cdd02c0 /on heap, that's no problem
}
int main()
{
vector<A> persons;
printf(" persons: %p\n", persons); // persons: 0x7ffc6cc981c0 ------------1
printf("&persons: %p\n", &persons);//&persons: 0x7ffc6cc981a0 ------------2
insert(persons);
printf("&p[0]: %p\n", &persons[0]);// &p[0]: 0x55b54cdd0350
printf("persons: %p\n", persons); // persons: 0x7ffc6cc981c0 /same as above
cout << persons.size() << endl; //1
}
编辑:我很抱歉,5 和 6 之间的区别不是真的,我不小心删除了一个 push_back,我为你感到很抱歉,希望没有让你感到困惑.
格式说明符 %p
要求参数的类型为 void*
。如果传递错误类型的参数,则程序的行为是未定义的。
printf(" persons: %p\n", persons);
在这里,您传递了一个类型为 vector<A>
的参数,因此程序的行为是未定义的。
因为参数甚至不是指针,所以没有希望输出有意义的内容。
printf(" persons: %p\n", &persons);
在这里,您传递了一个类型为 vector<A>*
的参数,因此程序的行为是未定义的。
在这种情况下,参数至少是一个指针。在所有指针都具有相同表示的系统上,输出可能是有意义的并表示存储指向对象的地址。但是,这仍然违反了参数类型的前提条件,不应依赖该行为。
结论:
- 不要在
printf
中使用错误的类型,否则行为将是未定义的。仔细研究文档。
- 任何 class 类型都没有正确的格式说明符。
- 不要使用
printf
。很难正确使用,还有更简单的选择。
太疯狂了!
为了弄清楚对象在C++中是如何存储在内存中的,
我写了下面的代码来查看变量的地址。
但是事情变得更加混乱。
所以在下面我想知道
为什么 1 不同于 2 ------这是否意味着它是一个指针?但是为什么?
为什么 1 与 3 不同 ------ 它是通过引用传递的,它们应该相同?!
#include <iostream>
#include <vector>
using namespace std;
class A {
public:
A(int age, string name) : age_(age), name_(name){};
void SetAge(int age) {
age_ = age;
}
int age_;
string name_;
};
void insert(vector<A>& p) {//passed by reference
A a1{1, "tom"};
printf(" p: %p\n", p); // p: 0x7ffc6cc98080 ------------3
printf("&p: %p\n", &p);//&p: 0x7ffc6cc981a0 ------------4
printf("&a1: %p\n", &a1); // &a1: 0x7ffc6cc980c0 /on stack, that's no problem
p.push_back(a1);
printf("&p[0]: %p\n", &p[0]); // &p[0]: 0x55b54cdd02c0 /on heap, that's no problem
}
int main()
{
vector<A> persons;
printf(" persons: %p\n", persons); // persons: 0x7ffc6cc981c0 ------------1
printf("&persons: %p\n", &persons);//&persons: 0x7ffc6cc981a0 ------------2
insert(persons);
printf("&p[0]: %p\n", &persons[0]);// &p[0]: 0x55b54cdd0350
printf("persons: %p\n", persons); // persons: 0x7ffc6cc981c0 /same as above
cout << persons.size() << endl; //1
}
编辑:我很抱歉,5 和 6 之间的区别不是真的,我不小心删除了一个 push_back,我为你感到很抱歉,希望没有让你感到困惑.
格式说明符 %p
要求参数的类型为 void*
。如果传递错误类型的参数,则程序的行为是未定义的。
printf(" persons: %p\n", persons);
在这里,您传递了一个类型为 vector<A>
的参数,因此程序的行为是未定义的。
因为参数甚至不是指针,所以没有希望输出有意义的内容。
printf(" persons: %p\n", &persons);
在这里,您传递了一个类型为 vector<A>*
的参数,因此程序的行为是未定义的。
在这种情况下,参数至少是一个指针。在所有指针都具有相同表示的系统上,输出可能是有意义的并表示存储指向对象的地址。但是,这仍然违反了参数类型的前提条件,不应依赖该行为。
结论:
- 不要在
printf
中使用错误的类型,否则行为将是未定义的。仔细研究文档。 - 任何 class 类型都没有正确的格式说明符。
- 不要使用
printf
。很难正确使用,还有更简单的选择。