C++ 创建并初始化对象

创建并初始化C++对象

当我们创建一个C++对象时,它需要占用一些内存,即使我们写一个完全为空的类,类中没有成员,什么也没有,它至少也要占用一个字节的内存。但是我们类中有很多成员,它们需要存储在某地方,当我们决定开始使用这个对象时,我们会创建一堆变量,对象有一堆变量,我们需要在电脑的某个地方分配内存,这样我们就可以记住这些变量设置的值。

应用程序会将内存主要分为两部分,栈和堆,还有其他部分的内存,比如源代码的区域。

在C++中我们要选择对象要放在哪里,对象是在栈上还是在堆上创建,它们有不同的功能差异。

栈:栈对象有一个自动的生存期,他们的生存期实际上是由它声明的地方的作用域决定的,只要变量超出作用域,也就是说内存被释放了,因为当作用域结束的时候,栈会弹出作用域里面的东西,栈上的任何东西会被释放。

堆:一旦在堆中分配一个对象,实际上你已经在堆上创建了一个对象,它会一直待在那里,直到你做出决定,确定不需要它,想要释放这个对象,那怎末处理这段内存都行。
 

代码案例:

在栈上创建: 

在什么时候在栈上创建对象?

几乎所有的时候,如果你能像这样在栈上创建对象,那就像这样创建对象,因为这是C++中最快的方法,也是可以管控的方法,去初始化对象

某些情况下不能这么做的原因?

1、如果将实例化对象放到main函数的生存期外

void Function()
	{
		 int a = 2;
		Entity entity;
	}

一旦到达函数结尾的花括号,这个entity会从内存中被销毁
当我们在main函数中调用Function时,就为这个函数创建了一个栈结构,它包含了我们声明的所有局部变量,其中包括基本类型,也包括我们的类和对象,当函数结束时,栈帧会被销毁,即栈上所有的内存,所有创建的变量都消失了

如果想让括号{}内的实例化对象在作用域之外依然存在,就不能分配到栈上,需要使用堆分配。

2、如果entity的规模太大,可能有太多的entity,可能没有足够的空间在栈上分配,因为栈通常非常小,通常是1M/2M

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

class Entity
{
private:
	string m_Name;  //只有一个成员,是一个字符串
public:
	Entity() : m_Name("Unknown") {}
	Entity(const string& name) : m_Name(name) {}

	const string& GetName() const { return m_Name; }
};

int main()
{
	// 1、在栈上创建
	Entity entity; // 实际上调用了默认构造函数Entity() : m_Name("Unknown")
	cout << entity.GetName() << endl;
	Entity entity1("chen");// 等价于 Entity entity1 = Entity("chen")
	cout << entity1.GetName() << endl;
	/*
	在什么时候在栈上创建对象?几乎所有的时候
	如果你能像这样在栈上创建对象,那就像这样创建对象,因为这是C++中最快的方法,也是可以管控的方法,去初始化对象
	某些情况下不能这么做的原因?
	1、如果将实例化对象放到main函数的生存期外
	void Function()
	{
		 int a = 2;
		Entity entity;
	}一旦到达这个花括号,这个entity会从内存中被销毁
	当我们调用Function时,就为这个函数创建了一个栈结构,它包含了我们声明的所有局部变量,其中包括基本类型,也包括我们的类和对象,当函数结束时,栈帧会被销毁,即栈上所有的内存,所有创建的变量都消失了

	Entity* e;
	{
		Entity entity2("cherno");
		e = &entity2;
		cout << entity2.GetName() << endl;
	} 一旦出了{}作用域,就到达了栈端,entity2对象就已经不存在了
	如果想让括号{}内的实例化对象在作用域之外依然存在,就不能分配到栈上,需要使用堆分配

	cin.get();
	return 0;
}

在堆上创建:

在堆上创建,首先要做的就是在改变类型,将Entity改成Entity*,通过new关键字,这里最大的区别不是那个类型变成了指针,而是new关键字,new关键字是关键。

Entity* entity = new Entity("cherno");当我们调用new Entity时,会在栈上分配内存,调用构造函数,这个new Entity实际上会返回一个Entity*,它会返回entity在堆上被分配的内存地址。

使用new关键字必须调用delete释放内存

delete + 变量名:delete entity;

性能问题:在堆上分配要比栈花费更长的时间,而且在堆上分配的话,您必须手动释放被分配的内存

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

class Entity
{
private:
	string m_Name;  //只有一个成员,是一个字符串
public:
	Entity() : m_Name("Unknown") {}
	Entity(const string& name) : m_Name(name) {}

	const string& GetName() const { return m_Name; }
};

int main()
{
	// 2、在堆上创建
	/*
	在堆上创建,首先要做的就是在改变类型,将Entity改成Entity*,通过new关键字,这里最大的区别不是那个类型变成了指针,而是new关键字,new关键字是关键
	当我们调用new Entity时,会在栈上分配内存,调用构造函数,这个new Entity实际上会返回一个Entity*,它会返回entity在堆上被分配的内存地址
    */
	Entity* entity = new Entity("cherno");
	//释放内存
	//delete 变量名;
	delete entity;
	
	/*
	性能问题:在堆上分配要比栈花费更长的时间,而且在堆上分配的话,您必须手动释放被分配的内存
	*/
	cin.get();
	return 0;
}

创建对象的两种方法,如何选择?

如果对象太大,或者需要显示地控制对象的生存期,那就是用堆创建,其他情况就是用栈创建。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值