Cherno C++

1 枚举enum

// 枚举从0开始
	enum color {red, green, blue=5} c;
	c = green;

2 const

  1. 作用:定义常量、类型检查、防止修改、节省空间
  2. 定义常量:常量不可更改,且必须初始化。
  3. 指针与const:
// const位于*左侧,用于修饰指针所指的const对象
const char* a;
char const* a;
// const位于*右侧,用于修饰指针为const指针
char* const a;
// const指针指向const对象
const char* const a;

// 允许将非const对象的地址赋给指向const对象的指针
const int* ptr;
int val = 3;
ptr = &val;
// const指针必须初始化,且值不可更改
int* const ptr = &val;
// 指向const对象的const指针
const int val = 3;
const int* const ptr = &val;
  1. 对于自定义类型的输入参数,应采用常量引用的方式增加效率。
void func(const A &a) //尽量避免按值传递void func(A a)
  1. const在类中应用
    const对象只能访问const成员函数,非const对象可访问任意成员函数。

3 智能指针

class Entity //自定义类
{
public:
	Entity();
	~Entity();
	void Print();
};

// 智能指针,无需手动delete
std::unique_ptr<Entity> e = std::make_unique<Entity>();
std::unique_ptr<Entity> e(new Entity());
e->Print();

4 复制

  • 浅复制:只复制了对象的内容,如类中的成员变量,其地址指向同一个对象(raw,copy =>obj)。
  • 深复制:拷贝整个对象,通过复制构造函数Entity(const Entity& other)实现,其地址指向不同的对象(raw=>obj, copy=>obj)。

5 vector

std::vector<Entity> Entities;
// 遍历
for (Entity& e : Entities)
	e.Print();
// 作函数参数(常量引用)
void Function(const std::vector<Entity>& entities);
// 优化(减少复制)
Entities.reserve(3);	// 要求vector至少能容纳3个元素,避免不必要的重分配
Entities.push_back(e);	// push_back()先构造对象再复制构造一次,会导致性能损失
Entities.emplace_back(1, 2, 3); // emplace_back()可根据输入参数原地构造对象,避免复制

6 使用第三方库

  1. 将外部库的include文件夹和bin文件夹拷贝,并放置在工程文件夹中。
  2. 拷贝头文件目录 $(SolutionDir)ThirdParty/include(相对路径)到属性\C++\常规\附加包含目录。
  3. 拷贝库文件目录 $(SolutionDir)ThirdParty/bin 到链接器\常规\附加库目录。
  4. 对于静态链接,将库文件glfw.lib拷贝至链接器\输入\附加依赖项;
    对于动态链接,将指向dll的lib文件glfwdll.lib拷贝至链接器\输入\附加依赖项,并且将glfw.dll文件拷贝至输出的exe文件夹下。

7 函数多返回值处理

方法1:使用struct

// 返回变量
struct ReturnValue
{
	std::string name;
	int age;
};

// 多返回值函数
ReturnValue Function(const std::string& filepath)
{
	//do something
	return { out_name, out_age };
}

// 调用函数
auto person = Function("res/person/Annie.txt");
int score = FindClass(person.name, person.age);

方法2:利用引用传递在函数内修改变量

// 函数定义
void Function(const std::string& filepath, std::string& outName, int& outAge)
{
	//do something
	outName = ...;
	outAge = ...;
}

方法3:C++17特性structured binding

// 函数定义
std::tuple<std::string, int> Function(const std::string& filepath)
{
	//do something
	return { "Cherno", 24 };
}

// 调用函数
auto [name, age] = Function();

8 template

// 模板函数
template<typename T>
void Print(T value)
{
	std::cout << value << std::endl;
}

// 模板类
template<typename T, int N>
class Array
{
private:
	T m_Array[N];
public:
	int GetSize() const { return N; }
};

// 实例化
Array<std::string, 5> array;

9 Stack & Heap

Note:尽可能在stack中使用变量,除非数据较大或数据生命周期较长时,才使用heap。

int value = 5// stack分配
int* hvalue = new int// heap分配
*hvalue = 5

10 宏macro

在属性/C++/预处理器/预处理定义,根据debug/release模式添加PR_DEBUG/PR_RELEASE。

// 通常用于调试时记录信息
#ifdef PR_DEBUG
#define LOG(x) std::cout << x << std::endl
#else
#define LOG(x)
#endif // PR_DEBUG

int main()
{
	LOG("hello");
}

11 auto

自动推导数据类型,通常用于数据类型较长的情况,使用auto简化代码。

std::vector<std::string> strings;
for (std::vector<std::string>::iterator it = strings.begin();
	it != strings.end(); it++)	// 代码过长
for (auto it = strings.begin(); it != strings.end(); it++) // 使用auto简化

12 函数指针

void PrintValue(int value); // 待使用的函数
// 调用函数指针的函数
void ForEach(const std::vector<int>& values, void(*func)(int))
{
	for (int value : values)
		func(value);
}

// main()调用
ForEach(values, PrintValue);

13 lambda

auto lambda = [](int value) {return value > 3; }; //lambda表达式

std::vector<int> values = { 1,5,4,2,3 };
// 使用lambda寻找符合条件的值
auto it = std::find_if(values.begin(), values.end(),
	[](int value) { return value > 3; });	// *it = 5

14 Thread线程

#include <thread>

static bool s_Finished = false;	// 状态位

void DoWork()
{
	using namespace std::literals::chrono_literals;
	while (!s_Finished)
	{
		std::cout << "Working...\n";
		std::this_thread::sleep_for(1s);	// 线程以1s为间隔执行
	}
}

int main()
{
	std::thread worker(DoWork);

	std::cin.get();
	s_Finished = true;

	worker.join();
	std::cout << "Finished.\n";
}

15 计时

#include <chrono>

// 构造Timer计时器
struct Timer
{
	std::chrono::time_point<std::chrono::steady_clock> start, end;
	std::chrono::duration<float> duration;

	Timer()
	{
		start = std::chrono::high_resolution_clock::now();
	}
	~Timer()
	{
		end = std::chrono::high_resolution_clock::now();
		duration = end - start;
		float ms = duration.count() * 1000.0f;
		std::cout << "Timer took " << ms << " ms" << std::endl;
	}
};

void Function()	// 要计时的函数
{
	Timer timer;
	// do something
}

16 多维数组

int* array2d = new int[5 * 5];
	for (int y = 0; y < 5; y++)
	{
		for (int x = 0; x < 5; x++)
		{
			array2d[x + y * 5] = 2;
		}
	}

17 排序

#include <algorithm>

int main()
{
	std::vector<int> values = { 3, 5, 1, 4, 2 };
	std::sort(values.begin(), values.end());	//默认升序
	std::sort(values.begin(), values.end(), std::greater<int>());	//降序排序
	// 按返回的true/false排序,true则a排在前面,false则b排在前面,下例为降序
	std::sort(values.begin(), values.end(), [](int a, int b)
		{ return a > b; });
}

18 多态(虚函数)

class Base
{
public:
	Base(){}
	virtual ~Base(){}	//虚析构函数:防止基类指针不会调用子类的析构函数,从而引起的内存泄漏
	virtual std::string GetName();	//虚函数:允许基类指针调用子类函数
	virtual int GetScore() = 0;	//纯虚函数:只有声明,实现留给子类
};

class Derived : public Base
{
public:
	std::string GetName() override;
	int GetScore() override;
};

19 C++17特性optional

#include <optional>
#include <fstream>
std::optional<std::string> ReadFileAsString(const std::string& filepath)
{
	std::ifstream stream(filepath);
	if (stream)
	{
		std::string result;
		// read file
		stream.close();
		return result;
	}
	return {};
}
int main()
{
	std::optional<std::string> data = ReadFileAsString("data.txt");
	if (data.has_value())
		std::cout << "File read successfully.\n";
	else
		std::cout << "File could not be opened.\n";

	//若data存在,返回数据到value;否则返回Not present
	std::string value = data.value_or("Not present");	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值