C++Cherno 学习笔记day11 [41]-[44] C++运算符及重载、this、栈作用域生存期、智能指针

一、C++运算符及其重载

运算符:一种符号,通常代替一个函数来执行一些事情,(函数)
dereference逆向引用运算符,箭头运算符,+=运算符,用于内存地址的&运算符,左移运算符<<,new,delete,逗号运算符,(),[]

运算符重载:添加参数、创建,允许在程序中定义或更改运算符的行为,Java中不支持,(用得少)

#include <iostream>
#include <string>
//Java写法
struct Vector2
{
	float x, y;

	Vector2(float x, float y)
		: x(x), y(y) {
	}

	Vector2 Add(const Vector2& other) const
	{
		return Vector2(x + other.x, y + other.y);
	}

	Vector2 Multiply(const Vector2& other) const
	{
		return Vector2(x * other.x, y * other.y);
	}
};

int main()
{
	Vector2 position(4.0f, 4.0f);
	Vector2 speed(0.5f, 1.0f);
	Vector2 powerup(1.1f, 1.1f);
	Vector2 result = position.Add(speed.Multiply(powerup));

	std::cin.get();
}
#include <iostream>
#include <string>

struct Vector2
{
	float x, y;

	Vector2(float x, float y)
		: x(x), y(y) {
	}

	Vector2 Add(const Vector2& other) const
	{
		//return *this + other;
		//return operator+(other);
		return Vector2(x + other.x, y + other.y);
	}
	//运算符重载
	Vector2 operator+(const Vector2& other) const
	{
		return Add(other);
	}

	Vector2 Multiply(const Vector2& other) const
	{
		return Vector2(x * other.x, y * other.y);
	}
};

int main()
{
	Vector2 position(4.0f, 4.0f);
	Vector2 speed(0.5f, 1.0f);
	Vector2 powerup(1.1f, 1.1f);

	Vector2 result1 = position.Add(speed.Multiply(powerup));
	Vector2 result2 = position + speed;/** powerup;*/

	std::cin.get();
}
#include <iostream>
#include <string>

struct Vector2
{
	float x, y;

	Vector2(float x, float y)
		: x(x), y(y) {
	}

	Vector2 Add(const Vector2& other) const
	{
		return Vector2(x + other.x, y + other.y);
	}

	Vector2 operator+(const Vector2& other) const
	{
		return Add(other);
	}

	Vector2 Multiply(const Vector2& other) const
	{
		return Vector2(x * other.x, y * other.y);
	}

	Vector2 operator*(const Vector2& other) const
	{
		return Multiply(other);
	}
};

int main()
{
	Vector2 position(4.0f, 4.0f);
	Vector2 speed(0.5f, 1.0f);
	Vector2 powerup(1.1f, 1.1f);

	Vector2 result1 = position.Add(speed.Multiply(powerup));
	Vector2 result2 = position + speed * powerup;

	std::cin.get();
}

<<左移运算符

#include <iostream>
#include <string>

struct Vector2
{
	float x, y;

	Vector2(float x, float y)
		: x(x), y(y) {
	}

	Vector2 Add(const Vector2& other) const
	{
		return Vector2(x + other.x, y + other.y);
	}

	Vector2 operator+(const Vector2& other) const
	{
		return Add(other);
	}

	Vector2 Multiply(const Vector2& other) const
	{
		return Vector2(x * other.x, y * other.y);
	}

	Vector2 operator*(const Vector2& other) const
	{
		return Multiply(other);
	}
};

std::ostream& operator<<(std::ostream& stream, const Vector2& other)
{
	stream << other.x << ", " << other.y;
	return stream;
}

int main()
{
	Vector2 position(4.0f, 4.0f);
	Vector2 speed(0.5f, 1.5f);
	Vector2 powerup(1.1f, 1.1f);

	Vector2 result1 = position.Add(speed.Multiply(powerup));
	Vector2 result2 = position + speed * powerup;

	std::cout << result2 << std::endl;

	std::cin.get();
}

在这里插入图片描述

友元函数

允许一个非成员函数访问类的私有(private)和保护(protected)成员。

类比:你的朋友被允许进入你家卧室(私有区域),而普通客人只能待在客厅(公共区域)。

class Vector {
private:
    int x, y;
public:
    Vector(int x, int y) : x(x), y(y) {}
    
    // 声明友元函数
    friend std::ostream& operator<<(std::ostream& os, const Vector& v);
};

// 定义友元函数(无需类作用域::)
std::ostream& operator<<(std::ostream& os, const Vector& v) {
    os << "(" << v.x << ", " << v.y << ")"; // 现在可以访问私有成员!
    return os;
}

// 使用
Vector v(3, 4);
std::cout << v; // 输出 (3, 4)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

友元函数是类的“特权朋友”,谨慎授予权限。

适用场景:运算符重载、跨类协作等特殊需求。

核心原则:优先用成员函数和公有接口,必要时再用友元。

tostring函数

在java C#中经常被用来重写

	bool operator==(const Vector2& other) const
	{
		return x == other.x && y == other.y;
[添加链接描述](https://en.cppreference.com/w/cpp/language/operators)	}

	bool operator!=(const Vector2& other) const
	{
		return !(*this == other);
		//return !operator==(other);
	}
	if (result1 == result2)
		std::cout << "Both results are equal!" << std::endl;

operator overloading

在这里插入图片描述
总结
运算符重载让自定义类型与内置类型行为一致,提升代码可读性。
遵循惯例:保持运算符的天然语义,避免反直觉设计。
慎用重载:仅在逻辑明确时使用,避免过度工程化。

二、C++中的this关键字

this关键字:可以访问成员函数,属于某个类的函数或者方法
在方法内部可以引用this
this是一个指向当前实例的指针,该方法属于这个对象实例

定义:this是一个常量指针,指向当前对象的内存地址。

作用:在成员函数中访问对象的成员变量和成员函数。

存在性:所有非静态成员函数(包括const函数)都隐含this指针,无需显式声明。

#include <iostream>
#include <string>

void PrintEntity(const Entity& e);

class Entity
{
public:
	int x, y;

	Entity(int x, int y)
	{
		this->x = x;
		this->y = y;

		Entity& e = *this;

		PrintEntity(*this);
		//delete this;
	}

	int GetX() const
	{
		const Entity& e = *this;
	}
};

void PrintEntity(Entity* e)
{
	//Print
}

int main()
{
	std::cout << "Hello World!" << std::endl;
	std::cin.get();
}

this,指向当前对象的指针。
也就是说这个指针指向当前的对象

#include<iostream>
//我们创建一个player类,用x,y来表示其坐标
class Player
{
  int x,int y;
  //再创造一个方法
  Fuzhi(int a,int b)
 {
  (*this).x=a;
  (*this).y=b;
 }
}

int main()
{
 Player biubiu_master;//这里我们创建一个名为biubiu之主的玩家类型
 biubiu_master.Fuzhi(114,514);
//注意看我们对biubiu之主对象使用Fuzhi这个方法的时候,回去看看这个Fuzhi方法,它里面做的事情是这个:  (*this).x=a;(*this).y=b;
//现在调用函数的对象是biubiu_master这个对象,所以方法当中的this指针指向biubiu之主这个对象,所以这个时候(*this),就是biubiu之主了
 return 0
}

三、C++的对象生存周期(栈作用域生存期)

在C++中,对象的栈作用域生存期(Stack Scope Lifetime)是指对象在其定义的作用域内(如函数、代码块)自动创建和销毁的过程。这是C++管理内存和资源的核心机制之一,尤其与RAII(Resource Acquisition Is Initialization)原则密切相关。

栈作用域生存期的核心规则
1、创建时机:对象在定义时调用构造函数。
2、销毁时机:对象在离开其作用域时自动调用析构函数。
3、存储位置:对象内存分配在**栈(Stack)**上(非静态局部变量)。
4、顺序原则:构造顺序与定义顺序一致,析构顺序相反(后进先出)。

在这里插入图片描述
在这里插入图片描述

栈:一种数据结构,可以在上面堆叠一些东西

基于栈的变量和基于堆的变量在对象生存期上的区别
基于栈的变量:在一出作用域就被释放、被摧毁

#include <iostream>
#include <string>

class Entity
{
public:
	Entity()
	{
		std::cout << "Created Entity!" << std::endl;
	}

	~Entity()
	{
		std::cout << "Destoryed Entity!" << std::endl;
	}
};

int main()
{
	{	//堆分配
		Entity* e = new Entity();
		//栈分配
		//Entity e;
	}
	std::cin.get();
}

在这里插入图片描述

#include <iostream>
#include <string>

class Entity
{
public:
	Entity()
	{
		std::cout << "Created Entity!" << std::endl;
	}

	~Entity()
	{
		std::cout << "Destoryed Entity!" << std::endl;
	}
};

int main()
{
	{	//堆分配
		//Entity* e = new Entity();
		//栈分配
		Entity e;
	}
	std::cin.get();
}

在这里插入图片描述
作用:类的作用域
比如智能指针smart_ptr unique_ptr
作用域指针 或作用域锁 scoped_lock
作用域指针 :基本上是一个类,是一个指针的包装器,在构造时用堆分配指针,析构时删除指针

#include <iostream>
#include <string>

class Entity
{
public:
	Entity()
	{
		std::cout << "Created Entity!" << std::endl;
	}

	~Entity()
	{
		std::cout << "Destoryed Entity!" << std::endl;
	}
};

// 基本的作用域指针(类)
class ScopedPtr
{
private:
	Entity* m_Ptr;
public:
	ScopedPtr(Entity* ptr)
		: m_Ptr(ptr)
	{
	}

	~ScopedPtr()
	{
		delete m_Ptr;
	}
};

int main()
{
	{
		ScopedPtr e = new Entity();
	}
	std::cin.get();
}

在这里插入图片描述
总结
栈作用域生存期是C++自动管理对象生命周期的核心机制。
核心原则:对象的生命周期严格绑定到其作用域,构造和析构自动调用。
关键优势:避免内存泄漏、简化代码、确保异常安全。
注意事项:避免返回悬空引用/指针,谨慎处理跨作用域的对象传递。

mutex locking 互斥锁

如果想锁定一个函数,以便多个线程可以同时访问它而不会爆炸,可以有一个自动作用域锁定。在函数开头锁定,在函数结束解锁。线程很快会出现
核心功能:防止多个线程同时访问共享资源,避免数据竞争(Data Race)。
类比:储物柜的每个柜子一次只能被一个人使用,使用时上锁,用完后解锁。

#include <mutex>
#include <thread>

std::mutex mtx;         // 全局互斥锁
int sharedData = 0;     // 共享资源

void safeIncrement() {
    mtx.lock();         // 加锁
    sharedData++;       // 安全操作共享数据
    mtx.unlock();       // 解锁
}

int main() {
    std::thread t1(safeIncrement);
    std::thread t2(safeIncrement);
    t1.join();
    t2.join();
    // 最终 sharedData = 2
}

常见问题:死锁Deadlock、递归锁(std::recursive_mutex)

四、C++的智能指针

智能指针:本质:一个原始指针的包装
当创建一个智能指针,会调用new并为你分配内存,然后基于你使用的智能指针,这些内存会在某一时刻自动释放。

unique_ptr 作用域指针

超出作用域时会被销毁,然后调用delete,不能复制、共享
在这里插入图片描述

#include <iostream>
#include <string>
#include <memory>

class Entity
{
public:
	Entity()
	{
		std::cout << "Created Entity!" << std::endl;
	}

	~Entity()
	{
		std::cout << "Destoryed Entity!" << std::endl;
	}
	
	void Print(){}
};

int main()
{
	{
		std::unique_ptr<Entity> entity = std::make_unique<Entity>();
		entity->Print();
	}	
	std::cin.get();
}

shared_ptr 共享指针

实现方式取决于编译器和你在编译器中使用的标准库
通常:引用计数
引用计数是一种方法,可以跟踪你的指针有多少个引用
一旦引用计数达到零,就被删除
在这里插入图片描述

#include <iostream>
#include <string>
#include <memory>

class Entity
{
public:
	Entity()
	{
		std::cout << "Created Entity!" << std::endl;
	}

	~Entity()
	{
		std::cout << "Destoryed Entity!" << std::endl;
	}
	
	void Print(){}
};

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

shared_ptr 需要分配另一块内存,叫做控制块,用来存储引用计数

weak_ptr 弱指针

在这里插入图片描述

int main()
{
	{
		std::shared_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			//不会增加引用计数
			std::weak_ptr<Entity> weakEntity = sharedEntity;
			e0 = sharedEntity;
		}	
	}
	std::cin.get();
}

软链接和硬链接

两种不同的文件引用方式。它们的核心区别在于如何指向文件数据
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

硬链接是数据的“分身钥匙”,删除原文件不影响其他钥匙。
软链接是路径的“路标牌”,原文件消失后路标失效。

选择原则:
需要数据保护 → 硬链接;
需要灵活引用 → 软链接。

在这里插入图片描述
总结:
优先使用unique_ptr 作用域指针,较低开销
如果需要在对象之间共享,不能使用unique_ptr时,使用shared_ptr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值