postncdestroy delete this 时断点_C++零基础16:this,stack,heap,smart pointer

最好的C++教程_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.com
6e5c706d1bcaff746462643fb2cbf7a0.png

this 关键字是一个指针,指向的是方法指向的当前的类的实例。当我们定义类的一个non-static的方法时,必须首先有一个对象,然后才能调用这个方法。譬如下面的代码:

#include <iostream>

class Entity {
public:
	int x, y;
	Entity(int x, int y)
	{
	
	}

};

int main() {


	std::cin.get();
}

这是如果想在构造函数中赋值,可以看到成员变量和参数是同名的,这时就可以使用this来进行区分:【当然,此时也可以使用初始化列表来进行赋值】

class Entity {
public:
	int x, y;
	Entity(int x, int y)
	{
		this->x = x;
		this->y = y;
	}

};
int main() {


	std::cin.get();
}

注意,this实际上是个指针,

Entity *  e = this;

所以这里需要使用->,或者使用(*this).x。

this还有一个用处是在类函数中调用外部函数,而又需要将自己作为参数进行传递。

#include <iostream>

void PrintEntity(Entity* e);


class Entity {
public:
	int x, y;
	Entity(int x, int y)
	{
		this->x = x;
		this->y = y;
		PrintEntity(this);
	}

};

void PrintEntity(Entity* e) {
}

int main() {


	std::cin.get();
}

比较浅显,感觉this比较神秘


下面是stack和heap。之前一直在说stack的作用域问题,下面看一个代码的例子:

#include <iostream>

class Entity{
public:
	Entity()
	{
		std::cout << "created Entity!" << std::endl;
	}
	~Entity()
	{
		std::cout << "destroyed Entity!" << std::endl;
	}
};

int main() {
	{
		Entity e;
	}

	std::cin.get();
}

运行结果如下:

be8d6c71c443aec9f0175bcddf5bdcdb.png

还可以断点调试一下,效果更明显。

如果将代码改成

Entity * e = new Entity();

下面是一个错误的例子:

int * CreateArray(){
int array[50];
return array;
}

上面的代码,一旦调用,栈上的空间也被清除了,因此不可能返回一个数组;

正确的做法是:1. 分配在堆上

int * CreateArray(){
int array = new int[50];
return array;
}

或者2. 先在调用的函数中创建好空间,然后在CreateArray中进行操作:

void CreateArray( int * array){
//fill the array

}

int main(){
int array[50];
CreateArray(array);
}

下面的代码实现的是在栈上分配一个指针,然后当scope结束的时候,自动删除,也成为scoped pointer。

#include <iostream>

class Entity{
public:
	Entity()
	{
		std::cout << "created Entity!" << std::endl;
	}
	~Entity()
	{
		std::cout << "destroyed Entity!" << std::endl;
	}
};

class ScopedPtr {
private:
	Entity* m_Ptr;
public:
	ScopedPtr(Entity * ptr)
		: m_Ptr(ptr)
	{
		
	}
	~ScopedPtr()
	{
		delete m_Ptr;
	}
};


int main() {
	{
		ScopedPtr * e = &ScopedPtr(new Entity());
	}

	std::cin.get();
}

不明白有什么样的应用场景~~Cherno讲了一个timer的例子,什么时候进入,什么时候退出;以及locks,还是不是很清楚......


smart pointer:是一种巧妙的C++技术;使得可以避免在使用new的时候一定要使用delete。或者,在C++编程的时候根本不用调用new 和 delete。smart pointer是一种wrapper,包装了基本的指针;当调用smart pointer的时候,会自动调用new,而在某个阶段,会自动调用delete。

第一个例子是unique pointer。unique pointer是一种scoped pointer,充分利用了栈自动销毁的特性。Unique Pointer不能复制,因为如果有两个Unique pointer指向同一块内存空间,当一个pointer删除的时候,它会释放那块空间,那么另一个指针指向的就是无效空间了。

#include <iostream>
#include <memory>

class Entity{
public:
	Entity()
	{
		std::cout << "created Entity!" << std::endl;
	}
	~Entity()
	{
		std::cout << "destroyed Entity!" << std::endl;
	}
};

int main() {
	{
		std::unique_ptr<Entity> entity(new Entity());
	}

	std::cin.get();
}

貌似unique_ptr是一个模板,这种用法。另外,unique_ptr有explicit关键字,所以必须显式调用构造函数。

如果想要进行复制,会报错。

std::unique_ptr<Entity> e1 = entity;

因为复制赋值的操作符 = 被设计成:

unique_ptr(const _Myt&) = delete;
Myt& operator=(const _Myt&) = delete;

防止自掘坟墓,英文中有类似的表达——digging yourself into a grave.

如果想要复制,那么有shared pointer。shared pointer要更复杂一点,因为它需要悄悄完成更多的工作,基本而言,使用了reference counting【类似于软链接】。也就是必须的自己记下来到底有几个指针指向这块内存,只有当count为0的时候,才说明没有指针指向这块内存,此时内存才能释放。

#include <iostream>
#include <memory>

class Entity{
public:
	Entity()
	{
		std::cout << "created Entity!" << std::endl;
	}
	~Entity()
	{
		std::cout << "destroyed Entity!" << std::endl;
	}
};

int main() {
	{
		std::unique_ptr<Entity> entity(new Entity());
		std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
		std::shared_ptr<Entity> e0 = sharedEntity;
	}
	std::cin.get();
}

上面代码的运行结果如下:

f03ffd9da4ca30a2eec4401f865e2713.png

特点都是离开了{} 范围,就自动销毁。

下面的代码也挺有意思的:

int main() {
	{
		std::shared_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity;
		}
	}
	std::cin.get();
}

对这个代码而言,最里边的{}结束时,sharedPtr并不会销毁。因为外部还有引用。只有在e0也结束的时候,才调用了析构函数。

居然还有个weak_ptr,不会增加reference。

int main() {
	{
		std::weak_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity;
		}
	}
	std::cin.get();
}

这种情况下,在最内层的{}结束后,sharedEntity就释放了。

感觉到底啥时候用还是不清楚啊~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值