C++,类的对象,其地址,栈上还是堆上?

本文详细介绍了C++中指针的概念、如何使用指针进行内存操作,以及堆和栈的区别。通过实例展示了指针如何指向堆上的内存,并演示了如何在堆上分配和释放资源。

 地址,存贮空间,指针自身在哪里,指针指向的存储空间的地址是? 大小是?

#include <iostream>
#include <string>
using namespace std;

class Student
{
public:
	// 存
	void setname(string s){	name = s;}
	void setage(int y){age = y;	}
	void setaddress(string add){address = add;}    
	// 取
	string getname(){return name;}
	int getage(){return age;}
	string getaddress(){return address;}

	
    //-- 引入构造函数:初始化成员,与类同名,没有返回值
	Student(string name,int age,string address)
	{
		this->name = name; this->age = age; this->address = address;      
	}
	

	~Student(){ 
	
	}
	
protected:
	
private:
	string name;
	int    age;
	string address;
};

void main()
{
    // x1在栈上,存储空间 36字节
	Student x1("刘莉莉x1",22,"东风路369号"); 
	cout<<"sizeof x1 = "<<sizeof x1<<"   &x1地址:"<<&x1<<endl; //36个字节

	// p1自身在栈上: 空指针不指向任何空间,但是这个变量本身是在程序空间的栈上的
	Student* p1 = NULL; 
	
	//  p1: 即p1指向的存贮空间(堆上)的首地址:但是还没有分配空间
	cout<<"sizeof p1 = "<<sizeof p1<<"   p1地址:"<<p1<<endl; 

   // &p1, 即p1自身的地址
	cout<<"sizeof p1 = "<<sizeof p1<<"   &p1地址:"<<&p1<<endl; 

    // 向 堆 上申请了36个字节的空间,堆地址是 p1
	p1 = new Student("刘莉莉p1",22,"东风路369号");

	// 36字节的存储空间大小,即p1指向存贮空间(堆上)的首地址
	cout<<"sizeof *p1 = "<<sizeof *p1<<"   p1地址:"<<p1<<endl; 

	cout<<"sizeof p1 = "<<sizeof p1<<"   &p1地址:"<<&p1<<endl;	

	cout<<"sizeof p1 = "<<sizeof p1<<"   p1地址:"<<p1<<endl; 
	

	Student x2("刘莉莉x2",22,"东风路369号");
	cout<<"sizeof x2 = "<<sizeof x2<<"   &x2地址:"<<&x2<<endl;	

	delete p1;

}

 

 //-----------------------  

 简化下, 仅仅 输出 位于栈上的   &x1,&p1,&x2:

void main()
{
    // x1在栈上,存储空间 36字节
	Student x1("刘莉莉x1",22,"东风路369号"); 
	cout<<"sizeof x1 = "<<sizeof x1<<"   &x1地址:"<<&x1<<endl; //36个字节

	// p1自身在栈上: 空指针不指向任何空间,但是这个变量本身是在程序空间的栈上的
	Student* p1 = NULL;  

    // 向 堆 上申请了36个字节的空间,堆地址是 p1
	p1 = new Student("刘莉莉p1",22,"东风路369号");

	// &p1, 即p1自身的地址
	cout<<"sizeof p1 = "<<sizeof p1<<"   &p1地址:"<<&p1<<endl; 

	Student x2("刘莉莉x2",22,"东风路369号");
	cout<<"sizeof x2 = "<<sizeof x2<<"   &x2地址:"<<&x2<<endl;	

	delete p1;

}


12FF50 - 12FF4C = 50 -4C  = 16 -C = 16-12 =4

12FF4C - 12FF28 = 24  -----即10进制的36

 

可见: 

1 ,  &x1,&p1,&x2 是 栈上连续的3个地址, 有高地址到低地址.

2.  栈上地址 是由高地址向地址派发空间的.

 

 

 

### 判断 C++ 对象是否分配在堆上上 在 C++ 中,对象的内存分配方式决定了它是在堆上还是上。通过构造方式的不同可以判断对象的分配位置。 #### 1. 判断对象是否在堆上的方法 可以通过自定义来跟踪对象是否是在堆上创建的。例如,在基中重载 `operator new` 和 `operator delete` 并记录分配信息,从而判断对象是否来自堆内存[^1]。 以下是一个简化的实现示例: ```cpp #include <iostream> #include <unordered_set> class HeapTracked { private: static std::unordered_set<const HeapTracked*> heapInstances; public: void* operator new(size_t size) { void* ptr = ::operator new(size); heapInstances.insert(static_cast<HeapTracked*>(ptr)); return ptr; } void operator delete(void* ptr) noexcept { heapInstances.erase(static_cast<HeapTracked*>(ptr)); ::operator delete(ptr); } bool isOnHeap() const { return heapInstances.find(this) != heapInstances.end(); } }; std::unordered_set<const HeapTracked*> HeapTracked::heapInstances; class Asset : public HeapTracked { private: int value; public: Asset() : value(0) {} }; int main() { Asset a; std::cout << a.isOnHeap() << std::endl; // 输出 0,表示不在堆上 Asset* b = new Asset; std::cout << b->isOnHeap() << std::endl; // 输出 1,表示在堆上 delete b; return 0; } ``` 这种方法通过静态集合记录所有动态分配的对象,并在运行时检查当前对象是否存在于该集合中,从而判断其是否分配在堆上[^1]。 #### 2. 静态建立和动态建立的区别 C++对象的创建方式决定了它们的存储位置。静态建立(如 `Asset a;`)由编译器在栈空间中分配内存并调用构造函数;而动态建立(如 `Asset* ptr = new Asset;`)则使用 `new` 运算符在堆空间中分配内存,并调用构造函数进行初始化[^2]。 - **对象**:直接在函数作用域内声明的对象会分配在上。 - **堆上对象**:使用 `new` 创建的对象会分配在堆上,并需要显式释放。 #### 3. 控制对象只能在堆上上分配 若希望限制对象仅能在堆上分配,可以将析构函数设为私有。由于对象在离开作用域后会自动调用析构函数,如果析构函数不可访问,则不能在上创建对象[^3]。 ```cpp class HeapOnly { private: ~HeapOnly() {} // 私有析构函数 public: void destroy() { delete this; } // 提供销毁接口 }; int main() { // HeapOnly h; // 编译错误:无法访问析构函数 HeapOnly* obj = new HeapOnly(); obj->destroy(); // 正确:手动销毁 return 0; } ``` 若希望对象只能在上分配,可以将 `operator new` 设为私有或删除,防止使用 `new` 分配对象。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值