c++实用技巧的窥探,为自己的代码保驾护航起来
文章目录
目录
前言
作为新手或校招生初次参与公司中的项目,经常会出现无从下手,害怕编写代码出现各种问题的困惑,其实最好的上手方式就是看项目中的代码实现,然后开始学习模仿其中的编写,能够在理解的基础上就会效果更加的显著,大幅度提高个人的代码实践和学习能力。
今天也给大家提供几个常用的可以避坑的实用技巧。
具体的实用规则
1.规则一:尽量避免使用预处理器的方式
具体表现:比如常用的#define,可以优先考虑使用 const, enum替换。
理由一:预编译器不支持debug模式,出错时,容易影响追踪的实践。
#define MAX_VALUE 100.00 // 预编译器处理方式
const double MaxValue = 100.00; //建议替换方式。
2.规则二:对象使用前确保对象已经初始化
具体表现:常常在项目中出现一些低级代码,很多情况就是变量中默认的初始值并不是所设想的,而是有脏数据存在的可能性。
理由一:规避脏数据对业务逻辑的影响;
理由二:提高程序健壮性,防止多人开发存在理解不透彻,更改业务逻辑顺序后导致遗漏赋值的情况。
类型一:内置类型
int a; //局部变量时,常常默认就是为零,但存在某些情况下,这块地址中的变量内容有脏数据。
int a = 0; //建议方式。
类型二:构造函数
Animal::Animal(const std::string& name, int year, double height)
{
this->name = name;
this->year = year;
this->height = height;
} //构造函数采用赋值的方式初始化,不推荐。
优化方式:建议采用初始值列表方式。
Animal::Animal(const std::string&name, int year, double height)
:name(name), year(year), height(height)
{
} //小技巧:确保初始值列表和class中的声明次序相同。
3.规则三:多多使用const
一句话:巧妙利用编译器的功能,为我们的代码保驾护航。
//类型一:修饰局部变量
const double MaxValue = 1000.00;
//类型二:修饰函数参数
void isValidateStudent(cosnt String& str);
//类型三:修饰函数返回值和本体
const char& operator[](std::size_t position) const.
//类型四:修饰指针
char hello[] = "Hello";
const char* p = hello; //指针常量 - 指针指向常量
char* const p = hello; //常量指针 - 指针是常量。 (区分小技巧:看const 后面的真实对象即可)
4.规则四:利用对象的方式包裹一下资源更安全
一句话:将对象的自动化初始化和析构运用在资源上。
理由一:将资源放进对象内(智能指针),可以依赖C++的析构函数自动调用机制“确保资源释放”。
//存在一个类
class Animal
{
... //省略具体实现
}
void founction()
{
Animal* dog = createAnimal();
...//省略具体实现
delete dog;
}
//优化如下:
void founction()
{
std::auto_ptr<Animal> dog(createAnimal()); // 采用auto_ptr智能指针对象包裹一下,可以有其析构函数自动删除dog指针。
...//省略具体实现。
}
补充:企业中很多会根据自己的业务需求,提供类似FFPointer等类似的智能指针,其中提供一些线程保护机制,引用技术的方式。
5.规则五:让接口容易被使用而不会误用
一句话:好的接口应该容易被正确使用。
理由一:接口应该实现见名知意。
对于多人开发的项目,常常出现同一个接口多人开发的情况,问题就是出在很多人不清楚接口能够实现对应需求,还出现同一个功能有个类似的接口,仅仅是由于不清楚命名规则导致的。
理由二:提供与内置变量行为一致的接口。
理由三:成员变量声明为private。函数提供get和set接口控制,充分利用封装特性。
//存在一个如下类:
class Student
{
...
}
//函数使用方式一:
bool validateStudent(Student s);
//函数使用方式二: 优化方案
bool validateStudent(const Student& s); //知道传入的s对象不会改变时,非内置类型优先使用const 引用的方式传递。
6.规则六:转型动作需谨慎。
理由一:转型动作破坏了类型系统,导致类型不易识别,有时非常隐晦的问题。
理由二:优先使用c++的转型动作,c++做了分门别类的处理,更加容易辨识问题。
//类别一:const_cast 去除对象的常量性
//类别二:dynamic_cast 继承体系中的安全向下转型
//类别三:reinterpret_cast 一般不用
//类别四:static_cast 强迫隐式转换
小故事:在这个规则中,我们公司参与一个跨平台项目的开发工作时,代码出现很多莫名其怪的事件传递错误,导致整个软件的业务逻辑都错乱了,当时花了很多时间排查问题,后来就定位到是由于我们的应用框架的继承类中的virtual函数没有调用基类中对应的函数,导致出现各种问题。
class FFDoubleSpinBox : public QDoubleSpinBox
{
...
protected:
void resizeEvent(QEvent* event) override;
}
//有问题的方案实现
FFDoubleSpinBox::resizeEvent(QEvent* event)
{
this->show();
...
}
//优化方案
FFDoubleSpinBox::resizeEvent(QEvent* event)
{
QDoubleSpinBox::resizeEvent(event); //优化:优先调用基类中的函数实现。
this->show();
...
}
总结
今天提供了一些客户端c++的一些见解。帮助你编写代码更加有底气和实力。更加笃定自己的代码编写。
自我介绍:
大家好,我是无妨的小智,一家上市互联网公司的c++软件开发工程师,学习c++编程有接近五年的时间。
从事的代表性产品是Filmora,国内版万兴喵影,类似国内的字节剪映,目前主流的短视频行业。
产品在海外用户量上百万级别。热爱分享一些实用的c++编程知识,希望能够给正在学习c++的你提供一些帮助。
立志于输出有自己风格和实用的知识博主。
如果有什么需要交流的,也欢迎添加weixin,有更多链接.