C++编程良好习惯

1 不要使用 using namespace std 简化对函数的调用

  • 不好的习惯
#include ...
using namespace std;//把命名空间直接放在全局作用域
void Fuc(){
	string str;
}
int main(){
	cout << "STD";
	return 0;
}

虽然减少了每次对 std:: 的输入, 但会造成 空间污染using namespace这个命令的滥用,会导致在代码中在不同命名空间的相同名字的变量或者函数导致代码冲突。)

  • 良好的习惯
#include ...
using std::cin;
using std::cout;
using std::string;

只使用 using 命令声明具体要使用的函数或变量

2 不要使用 endl 换行

cout << endl;//bad,会刷新缓冲区(费时)
cout << '\n';

3 for loop

  • 避免使用 基于索引 的 for loop
void Func(const vector<int>& data){
	for(size_t i = 0; i < data.size(); i++){//这是基于索引的 for loop
		model.update(data[i]);
	}
}

  • 选择更能表达意图的 基于范围 的for loop
void Func(const vector<int>& data){
	for(const auto& x : data){
		model.update(x);
	}
}

4 const限制数据只读状态

  • 如果要编写一个函数将数组中的数据依次显示在终端上(即这个数组的数据对于这个函数来说只读不写),就应当加以 c o n s t const const 限制这个数据不能被该函数更改
void PrintPath(const vector<string>& path){
	for(const auto& point : path){
		cout << point << '\n';
	}
}

5 结构化绑定

  • 不易阅读
unordered_map<string, string> colors = {
				{ "RED", "#FF0000"},
				{"BLUE", "#00FF00"},
				{"GREEN", "#0000FF"}
}
for(const auto& pair : colors){
	cout << "name:" << pair.first << ",hex:" << pair.second << '\n';
}
  • structured binding结构化绑定后
for(const auto& [name, hex] : colors){//键值对
	cout << "name:" << name << ",hex:" << hex << '\n';
}

6 函数需要返回多个值时使用结构体

  • 示例
void Return(const int n, int& out1, int& out2) {
	out1 = n + 1;
	out2 = n * 2;
}
int main()
{
	int plus, mul;
	Return(1, plus, mul);
	cout << plus << mul;
}
  • 更改后
struct Ret2Val { int x; int y; };
Ret2Val Return(const int n) {
	return { n + 1 ,n * 2 };
}
auto [x, y]=Return(1);

7 对析构函数标记 virtual

  • 如果通过指向基类的指针删除派生类对象,那么派生类的析构函数将不会被调用,只有基类的析构函数会被调用
class Base{
public:
	~Base{
		...//called Base destructor
	}
	void foo(){
		...//do foo
	}
}
class Derived : public Base{
public:
	~Derived(){
		...//called Derived destructor
	}
}
void ConsumeBase(std::unique_ptr<Base> p){//使用unique_ptr使编译器自动调用对应的析构函数
	p->foo();
	...//删除指向基类的指针
}

如果是传递的派生类实例的指针将会错误的调用析构函数

  • 添加virtual,虚析构函数
virtual ~Derived(){}

为保证编译器正确地调用析构函数,即时通过的是基类实例的指针,也要将派生类的析构函数标记为虚函数

  • 还可以对派生类的析构函数进行显示标记
~Derived() override{}

8 类成员定义顺序存在一定依赖

  • 有问题的
class MyClass{
public:
	MyClass(char* start, size_t size) : _start{start}, _end{_start + size}{//初始化成员变量
	}
	virtual ~MyClass(){...}
}
private:
	char* _end;
	char* _start;

成员初始化的顺序是按照他们在声明中出现的顺序
_start_end 定义之后,会出现的问题是,在初始化_end_start+size 时,_start 还未(初始化)定义【此时的_start是个JunkValue】

  • 更改1:按照相同的顺序进行定义
  • 更改2:
MyClass(char* start, size_t size) : _start{start}, _end{start + size}

你可能感兴趣的:(c++)