• C++基础知识


    1.bind()

    函数对象:可以以函数方式与()结合使用的任意对象,包括 function 仿函数、函数名、函数指针、含有()操作符的类对象。

    function是一组函数对象包装类的模版,(又叫仿函数)实现一个泛型的回调机制,function< int( int, int)>形式,可调用的对象普通函数、函数指针、lanmbda表达式、函数对象和类的成员函数等。

    int add(int i, int j){ return a + b;}
    auto mod = [](int a, int b){  return a%b;}
    struct divide{
        int operator()(int i, int j){
            return i/j;  
        }
    };
    function<int(int, int)> func1 = add;
    function<int(int, int)> func2 = mod;
    function<int(int, int)> func3 = divide;
    func1(1, 2);
    int a = func2(1, 2);
    func3(1, 2);
    //bind
    template <class Fn, class... Args>
      /* unspecified */ bind (Fn&& fn, Args&&... args);

    bind返回一个和Fn功能相同,但参数是Args(已经填好了,调用时不用传参了)和占位符的函数对象,如果Fn是成员函数,则返回值第一个参数this指针。

    struct integer{
        int i;
        integer(int i):i(i){}
        void incr_by(int j) {i += j;}
    };
    
    integer x(0);
    integer* y = &x;
    using namespace std::placeholders;
    
    auto f0 = bind(&integer::incr_by, _1, _2);
    f0(x, 2); //x.incr_by(2);  x.i = 2;
    f0(y,2);//y->incr_by(2); x.i = 4;
    
    auto f1 = bind(&integer::incr_by, x, _1);
    f1(2); //这里x是值传递,调用的是一个临时对象的incr_by函数,x的i不改变。
    
    auto f2 = bind(&integer::incr_by, ref(x), _1);
    f2(2);//引用,x改变了,x.i = 6;
    
    auto f3 = bind(&integer::incr_by, &x, _1);
    f2(2);//指针,x改变了,x.i = 8;

     2.vitual

    c++在布局以及存取时间上主要的额外负担是vitual引起的,因此在真的需要运行时多态,才用虚函数(注意:必须是基类类型的指针或引用才触发动态绑定)。

    vitual函数:用于支持“执行期绑定”,以实现多态。  vitual继承: 用于实现类似菱形继承中的基类只有一个单一被共享的实体(A->B->D;A->C->D;vitual继承,则D中只有一个A的实体)。

    有虚函数的类在创建对象时,在构造函数中先生成一个虚函数表,表里依次存放所有虚函数的地址,生成的对象中有一个虚函数指针指向虚函数表。

    而生成派生类对象时,会先调用基类的构造函数,生成一个基类的虚函数表,然后调用派生类的构造函数,会覆盖虚函数表中同名的函数,从而实现多态(这就是c++里的动态连编:在程序运行时选择调用哪个函数)。

    而函数隐藏的目的则是:使父类的改动不会影响子类重载的调用

     3.const用法

    I.代替宏定义,定义常量

    II.const * 常量指针。 与 * const 指针常量。

    III.修饰函数返回值,常用在返回值为用户自定义类型。

    IV.修饰函数参数(一般为指针、引用),使得 非const 和 const类型(一般为值传递的临时对象)都能作为实参调用。

    V.在类中,修饰成员函数,反正()后面,表明此函数不能改变对象的成员变量,const对象只能调用const成员函数。

     4.内存管理

    c++动态内存可能出现的问题:

    I.内存泄露,new/delete 和 malloc/free 没有配套使用,或者在构造函数中new了之后抛出异常,就不会执行析构函数中的delete。

     解决方法:用智能指针代替new/delete管理对象,注意shared_ptr和 unique_ptr的区别(unique_ptr无法复制构造和赋值操作,但可以移动构造和移动赋值(如作为函数返回值)), 在遇上环形引用(类A中有类B的智能指针引用对象,类B中有类A的智能指针引用对象,两个都有一个对方的引用计数,无法析构)时使用一个weak_ptr。 

    II.野指针,指针未初始化且未指向null 或 指向一个已删除的对象(如函数体内局部对象,或delete后未置null),则指针会随机指向一块内存,很可能是本程序中已使用的内存或数据,如果此时通过此指针对该内存写操作,可能造成程序崩溃或数据污染,(且野指针难以发现,危害大)。

    解决方法:初始化时置null,释放时置null。

    III.内存碎片,频繁的使用new/malloc,由于所申请的内存大小不定而造成内存碎片。

    解决方法:内存池,在使用内存之前,先申请分配一定数量大小相同的内存块组成的内存池作备用,当有新的内存需求时,就从内存池分出一部分内存块,若内存块不够再申请新的内存。

    5.new/delete 和 malloc/free 比较

    I.new/delete 是c++运算符(运算符是编译器控制的,因此可以重载),malloc/free 是标准c库函数,不受编译器控制。

    II.malloc只负责申请一块一定长度的内存,而new不仅分配了内存,还进行了sizeof,类型转换,类型安全检查,还调用了构造函数,delete调用了析构函数。

    III.malloc/free需要库文件支持,而new/delete不需要。

  • 相关阅读:
    任何时候都适用的20个C++技巧
    C++ 解析Json——jsoncpp(转)
    C++标准库和标准模板库(转)
    string标准C++中的的用法总结(转)
    JOIN US | 京东智联云诚聘技术精英
    在线公开课 | 云原生下的DevOps与持续交付
    AI端侧落地,京东AI技术如何部署边缘?
    CVPR 2020 | 京东AI研究院对视觉与语言的思考:从自洽、交互到共生
    IOT、AI、云计算等融合技术推进制造业产业转型
    边缘计算2.0时代,“云边缘”与“边缘云”你分清了吗?
  • 原文地址:https://www.cnblogs.com/wukuaiqian/p/7746594.html
Copyright © 2020-2023  润新知