CPP高级语法(一)

297 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第3天,点击查看活动详情

CPP优化的几个原则:

BE A MAN MANAGE YOUR OWN MEMORY!

gw.subscribecdn.com/link/CTSPFI…

1、在函数传参时,如果可以尽量使用 const 和&(reference)这样可以有效减少消耗,因为他不会deep copy创建新的变量。

2、可以接受定义的复杂,不能接受调用的复杂。

3、尽量在栈上分配内存,只有当变量的生命周期需要比函数作用域更长及需要加载非常大的数据的时候再考虑在堆上分配(智能指针、new)。在栈上分配内存本质上就是一条汇编指令mov DWORD ptr *** , 5。而堆需要一大堆汇编。

www.bilibili.com/video/BV1By…


一、运算符重载

当不知道需要重载的运算符,接受及返回的参数样式时,可以将鼠标移到运算符上,VS会给出相应提示。

#include <iostream>
#include <string>

#include <iostream>
#include <string>

class Vector {
public:
	float x, y;
public:
	Vector(float x, float y)
		:x(x), y(y) {}
	Vector Add (const Vector& other)const {
		return *this+other;
	}
	Vector operator+ (const Vector& other)const {
		return Vector(x + other.x, y + other.y);
	}
	bool operator== (const Vector& other)const {
		return (*this).x == other.x && (*this).y == other.y;
	}
	bool operator!= (const Vector& other)const {
		return !(*this == other) ;
	}
};


//重载<<运算符 ,ostream代表output stream即输出流
std::ostream& operator<<(std::ostream& stream, const Vector& other) {
	stream << other.x << "," << other.y;
	return stream;
}

int main(int argc,char** argv){
    Vector v1 = Vector(2.1f, 2.2f);
	Vector v2 = Vector(2.1f, 2.2f);
	std::cout << v1+v2 << std::endl;
}

1、箭头运算符重载

#include<iostream>
#include<string>

struct Vector3
{
	float x, y, z;

};

int main()
{
	int offse_x = (int)&((Vector3*)0)->x; 
	//int offse_x = (int)&((Vector3*)nullptr)->x;
	int offse_y = (int)&((Vector3*)0)->y; 
	//int offse_y = (int)&((Vector3*)nullptr)->y;
	int offse_z = (int)&((Vector3*)0)->z; 
	//int offse_z = (int)&((Vector3*)nullptr)->z;
	std::cout << offse_x << std::endl;
	std::cout << offse_y << std::endl;
	std::cout << offse_z << std::endl;

	std::cin.get();
}

代码解释:

因为"指针->属性"访问属性的方法实际上是通过把指针的值和属性的偏移量相加,得到属性的内存地址进而实现访问。而把指针设为nullptr(0),然后->属性就等于0+属性偏移量。编译器能知道你指定属性的偏移量是因为你把nullptr转换为类指针,而这个类的结构你已经写出来了(float x,y,z),float4字节,所以它在编译的时候就知道偏移量(0,4,8),所以无关对象是否创建。

二、CPP智能指针(Smart Pointer)

智能指针的存在是为了避免程序员在new出一片堆内存空间后忘记delete,防止内存泄漏。

用new在内存堆空间创建实例后,我们需要用delete销毁实例,智能指针是使该过程自动化的一种方法。

#pragma once

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

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

	}

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

	void print() {
		std::cout << "print" << std::endl;

	}
};

1、唯一指针(unique_pointer)

unique_ptr 不能被复制,栈消失时自动被销毁,几乎没啥消耗,只是为了避免内存泄漏而存在。

unique_ptr源代码中,通过运算符重载的方式删除了=符号。同时将unique_ptr的copy constructer也给delete

int main(){
    {
        std::unique_ptr<Entity> entity(new Entity()); //构造方式一
        std::unique_ptr<Entity> entity = std::make_unique<Entity>(); //构造方式二,推荐
        
        std::unique_ptr<Entity> entity2 = entity;//报错,unique_ptr 不能被复制
        entity->print();
    }//越出该scope unique_ptr就会被释放
}

2、分享指针(shared_pointer)

当指向shared_pointer的reference count为0时被销毁。让程序员可以在不同objects之间分享内存

	{
		std::shared_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity;
		}//此时尽管已经越出该作用域(scope)但是cpp不会销毁该指针,因为sharedEntity赋值给了e0,此时refenrence count不为0
		
	}

3、弱指针(weak_pointer)

当shared_ptr赋值给weak_ptr时,不会增加reference count。

	{
		std::weak_ptr<Entity> e0;
		{
			std::shared_ptr<Entity> sharedEntity = std::make_shared<Entity>();
			e0 = sharedEntity; //赋值给weak_ptr时不会增加reference count
		}//因此出了这个scope sharedEntity就会被销毁。
		
	}