• Effective C++


    从C转向C++

    1. 尽量用const和inline而不是#define

    define的缺点:无类型安全,无运行期错误提示。预处理命令,快速。
    const 修饰常量,inline函数使用定义式替换调用式但具有参数类型判断。
    csdn

    1. 尽量用而不用<stdio.h>

    命名空间保护,语法标准偏向C++。

    1. 尽量用new和delete而不用malloc和free

    new和delete对构造函数和析构函数的调用,是C++对象构造/析构构成中不可少的步骤。

    内存管理


    正确得到和有效使用内存


    1. 尽量使用C++风格的注释

    C++风格的注释是指"//"行尾注释法。why? /* */ 不允许嵌套

    1. 对应的 new 和 delete 要采用相同的形式

    申请一个对象数组:new [],而释放一个对象数组:delete [],同样的不同对象的内存申请和释放使用new&delete。

    1. 析构函数里对指针成员调用 delete

    如果写了new一定要有一个delete与之对应,一个对象对资源的申请和释放一般是在构造函数和析构函数中的。
    使用智能指针替换普通裸指针。

    1. 预先准备好内存不够的情况

    new 无法申请到足够内存时会抛出异常(std::bad_alloc)
    可以通过设置处理函数,控制内存不够时的行为 set_new_handler
    一个设计得好的 new-handler 函数必须实现下面功能中的一种:

    • 产生更多的可用内存。
    • 安装另一个不同的 new-handler 函数。
    • 卸除 new-handler。
    • 抛出 std::bad_alloc 或从 std::bad_alloc 继承的其他类型的异常。
    • 没有返回。
    1. 写 operator new 和 operator delete 时要遵循常规
    2. 避免隐藏标准形式的 new

    某对象中声明重载operator new(而不定义)会导致标准new在当前类被覆盖。

    1. 如果写了 operator new 就要同时写 operator delete

    一个new一定要有一个delete与之对应,切delete释放的正是new申请的资源。

    1. 为需要动态分配内存的类声明一个拷贝构造函数和一个赋值操作符
    2. 尽量使用初始化而不要在构造函数里赋值

    初始化对象,而不初始化业务所需的资源。

    1. 初始化列表中成员列出的顺序和它们在类中声明的顺序相同

    类成员是按照它们在类里被声明的顺序进行初始化的,和它们在成员初始化列表中列出的顺序没一点关系。

    1. 确定基类有虚析构函数

    否则基类指针无法调用其真实派生对象的析构函数。

    1. 让 operator=返回*this 的引用

    可以通过.而非->继续链式调用。

    1. 在 operator=中对所有数据成员赋值

    不要遗漏,赋值是对整个对象进行赋值,以免有成员未得到正确数值。

    1. 在 operator=中检查给自己赋值的情况

    if(this == &other) 自我赋值会产生多余操作,对某些操作如memcpy等还会导致内存错乱。拥有动态内存的对象中甚至会导致越界等问题。

    类和函数:设计与声明

    1. 争取使类的接口完整并且最小

    最好不要有数据成员,尽量把一件事情交给同样的人做。同样的事情涉及的业务,提供所有的接口去完成

    1. 分清成员函数,非成员函数和友元函数
    1. 避免 public 接口出现数据成员

    导致数据可以直接访问,使用setter和getter

    1. 尽可能使用 const

    使不应该修改的数据可以

    1. 尽量用“传引用”而不用“传值”

    1、性能,2、配合const使用。

    1. 必须返回一个对象时不要试图返回一个引用

    返回引用的对象的生命周期不能小于函数调用处。

    1. 在函数重载和设定参数缺省值间慎重选择

    重载函数声明处的参数缺省值不一定起作用。如果你选用的是基类指针调用,参数缺省值选用的就是基类函数的。

    1. 避免对指针和数字类型重载

    如:void f(int x); 和 void f(string *ps); 在面对调用式:f(0)时冲突。

    1. 当心潜在的二义性

    语义和语法的二义性

    1. 如果不想使用隐式生成的函数就要显式地禁止它

    隐式生成的函数:拷贝构造,赋值运算,默认构造,默认析构。
    使用将函数声明为private的方式禁止

    1. 划分全局名字空间

    使用全局匿名命名空间分割
    尽量使用命名名称空间

    类和函数:实现

    1. 避免返回内部数据的句柄
    2. 避免这样的成员函数:其返回值是指向成员的非 const 指针或引用,但成员的访问级比这个函数要低
    3. 千万不要返回局部对象的引用,也不要返回函数内部用 new 初始化的指针的引用
    4. 尽可能地推迟变量的定义
    5. 明智地使用内联
    6. 将文件间的编译依赖性降至最低

    继承和面向对象设计

    1. 使公有继承体现 "是一个" 的含义
    2. 区分接口继承和实现继承
    3. 决不要重新定义继承而来的非虚函数
    4. 决不要重新定义继承而来的缺省参数值
    5. 避免 "向下转换" 继承层次
    6. 通过分层来体现 "有一个" 或 "用...来实现"
    7. 区分继承和模板
    8. 明智地使用私有继承
    9. 明智地使用多继承
    10. 说你想说的;理解你所说的
    11. 理解隐式接口和编译期多态

    什么是显示接口和运行时多态?

    一个显示的接口类,拥有可视的接口和其他约束。
    对虚函数的调用具有运行时多态的性质,具体调用的函数取决于this指针的类型。
    什么是隐式接口和编译器多态
    编译时多态即模板定义处的行为由模板参数传入的类型决定,可以在编译时确定。函数重载也属于编译时多态。
    隐式接口及模板定义处的一段表达式对模板类型做出的约束。

    杂项

    1. 弄清 C++在幕后为你所写、所调用的函数
    2. 宁可编译和链接时出错,也不要运行时出错
    3. 确保非局部静态对象在使用前被初始化
    4. 重视编译器警告
    5. 熟悉标准库
    6. 提高对 C++的认识
  • 相关阅读:
    python 使用pyinstaller生成exe,以及编译报错:编译时报错如下:No module named timedeltas not build. If you want import pandas from the source directory, you may need to run 'python setup.py build_ext --inplace --force' to
    Remote desktop manager 如何导入.db配置文件
    C# string怎么转换成泛型T?
    C# 如何在ComboBox输入文字改变时,触发事件?
    C# 检查panel所有的checkbox 是否被选中
    C# bool? 的意思
    WPF: Accessing Databases with Windows Presentation Foundation / WPF链接数据库
    WPF 03
    WPF MVVC 基础
    使用 Topshelf 创建 Windows 服务
  • 原文地址:https://www.cnblogs.com/xiangleili/p/11321671.html
Copyright © 2020-2023  润新知