两种方式,取决于我们在内存的哪个位置创建对象(堆heap或栈stack)

C++ 有一条基本准则:任何不同的对象在内存中都必须有唯一的地址。所以如果创建了两个对象class Empty {};Empty e1;Empty e2;,只有他们都有1字节大小的情况下,e1和e2才会有不同的内存地址

  • 栈上创建的对象,有自动的生命周期,由他们的作用域决定的,离开作用域则消失
  • 堆上创建的对象,会一直在,直到你手动释放它

栈上创建对象#

#include <iostream>
#include <string> 

//类型别名 (Type Alias) 声明。
using String = std::string;

// using 声明,使用的时候只能用string(只起到了省略std::的作用)
//using std::string; 

/*
- 如果你把"using String = ... 还是 using std::string;"写
在 .h (头文件) 的全局作用域里,都会产生“污染”:
- 任何 #include 你这个头文件的人,都会被强制接受你的命名习惯。
如果别人也定义了一个 String,代码就会崩溃(冲突)。
*/

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; }
};

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

int main()
{
	Function();
	Entity* e;
	{
		//在栈上创建对象(这里会默认调用默认构造函数)
		Entity entity3("Cherno");
		e = &entity3;
		std::cout << e->GetName() << std::endl;
	}

	//在栈上创建对象(这里会默认调用默认构造函数)
	Entity entity;
	std::cout << entity.GetName() << std::endl;
	//在栈上创建对象
	Entity entity1("Cherno1");
	std::cout << entity1.GetName() << std::endl;
	//在栈上创建对象
	Entity entity2 = Entity("Cherno2");
	std::cout << entity2.GetName() << std::endl;

	std::cin.get();
}

e = &entity3;加断点,并走到下一步

此时e指向的对象还有值,继续走到}之外

因为此时entity3对象被释放并被销毁了

不在栈上创建对象的原因

  • 超出作用域后对象自动销毁
  • 栈的空间远小于堆

在堆上创建对象#

#include <iostream>
#include <string> 

//类型别名 (Type Alias) 声明。
using String = std::string;

// using 声明,使用的时候只能用string(只起到了省略std::的作用)
//using std::string; 

/*
- 如果你把"using String = ... 还是 using std::string;"写
在 .h (头文件) 的全局作用域里,都会产生“污染”:
- 任何 #include 你这个头文件的人,都会被强制接受你的命名习惯。
如果别人也定义了一个 String,代码就会崩溃(冲突)。
*/

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()
{  
	Entity* e;
	{
		//在栈上创建对象(这里会默认调用默认构造函数)
		Entity* entity=new Entity("Cherno"); 
		e = entity;
		std::cout << entity->GetName() << std::endl;
		//!!必须手动释放内存
		//delete entity;
	} 

	//上面有意把delete entity;注释了
	std::cin.get();
	delete e;
	std::cin.get();
}

调试#

下一步