zoukankan      html  css  js  c++  java
  • C++基础知识:泛型编程

    1.泛型编程的概念

    ---不考虑具体数据类型的编程模式

    Swap 泛型写法中的 T 不是一个具体的数据类型,而是泛指任意的数据类型.


    2.函数模板

    - 函数模板其实是一个具有相同行为的函数家族,可用不同类型进行调用
    - 函数模板可以根据类型实参对函数进行推导调用
    - 函数模板可以显示的指定类型参数
    - 函数模板可以被重载

    ①函数模板的语法规则
    ―template    关键字用于声明开始进行泛型编程
    ―typename  关键字用于声明泛指类型

     ②函数模板的应用
    ―自动类型推导调用
    ―具体类型显示调用

     3.函数模板的深入理解
    ― 编译器并不是把函数模板处理成能够处理任意类型的函数
    ― 编译器从函数模板通过具体类型产生不同的函数
    ― 编译器会对函数模板进行两次编译
      - 在声明的地方对模板代码本身进行编译
      - 在调用的地方对参数替换后的代码进行编译


    4.函数模板与重载

    函数模板可以像普通函数一样被重载
       C++ 编译器优先考虑普通函数
       如果函数模板可以产生一个更好的匹配 , 那么选择模板
       可以通过空模板实参列表的语法限定编译器只通过模板匹配

    注意:

    5.多参数函数模板

    函数模板可以定义任意多个不同的类型参数

    当声明的类型参数为返回值类型时 , 无法进行自动类型推导。

    不完美解决方案:
    将返回类型参数声明到第一个参数位置 , 调用时只需显示声明返回类型参数即可。

     6.类模板

    一些类主要用于存储和组织数据元素
    ―如 : 数组类 , 链表类,链表类 , Stack类,Queue类等等
    C++中可以将模板的思想应用于类中,使得类的可以不关注具体所操作的数据类型,而只关注类所需要实现的功能 :

    声明的泛指类型 T 可用于声明成员变量和成员函数
    编译器对类模板的处理方式和函数模板相同
    ― 编译器从类模板通过具体类型产生不同的类
    ― 编译器在声明的地方对类模板代码本身进行编译
    ― 编译器在使用的地方对参数替换后的代码进行编译

    由于类模板的编译机制不同 , 所以不能像普通类一样分开实现后在使用时只包含头文件,在工程实践上 , 一般会把类模板的定义直接放到头文件中!!
    只有被调用的类模板成员函数才会被编译器生成可执行代码!!!

     类模板可以被特化:用 template<>声明一个类时, 表示这是一个特化类!

     特化类模板的意义:
      当类模板在处理某种特定类型有缺陷时 , 可以通过类模板的特化来克服处理这种特定类型带来的不足

    注意:编译器优先选择特化类生成对象!!

    类模板的局部特化:可以指定类模板的特定实现 , 并要求某些类型参数仍然必须得模板的用户指定

    为什么需要特化,而不重新定义新类 ?
    ― 特化和重新定义新类看上去没有本质区别, 但是如果定义新类, 那么将变成一个类模板和一个新类,使用的时候需要考虑究竟是用类模板还是用新类
    ― 而特化可以统一的方式使用类模板和特化类 , 编译器自动优先选择特化类


    非类型模板参数的限制:
      -函数模板和类模板的模板参数可以是普通数值
      -变量不能作为模板参数
      -浮点数和类对象不能作为模板参数
      -全局指针不能作为模板参数
      -编译器的推导过程是在编译阶段完成的, 因此,编译器的推导必须依赖于特化类,否则推导过程无法结束。

    怎么判断一个变量是否为指针???(模板与可变参数函数)

    -C++中仍然支持C语言中的可变参数函数
    -C++编译器的匹配调用优先级
      重载函数
      函数模板
      可变参数函数

    工程问题:内存泄露,内存多次释放,使用越界...

    内存越界的问题常发生于数组的使用中
    ―解决方案 : 数组类
    ―工程中, 在非特殊情况下 , 要求开发者使用预先编写的数组类对象代替C 语言中的原生数组

    ②内存泄漏和内存多次释放常发生于指针的使用过程中
    ―解决方案: 智能指针
    ―工程中 , 要求开发者使用预先编写的智能指针类对象代替 C 语言中的原生指针

    工程中的智能指针是一个类模板:
      ―通过构造函数接管申请的堆内存
      ―通过析构函数确保堆内存被及时释放
      ―通过重载指针运算符* 和 - > 模拟指针的行为
      ―通过重载比较运算符 == 和 != 模拟指针的比较

    7.智能指针的深入理解:

    STL常用的7种智能指针:std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::scoped_array、

                 boost::shared_array、boost::weak_ptr、boost:: intrusive_ptr

    ①std::auto_ptr:

    (1)    尽量不要使用“operator=”。如果使用了,请不要再使用先前对象。

    (2)    记住 release() 函数不会释放对象,仅仅归还所有权。

    (3)    std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。

    (4)    由于 std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。

    ②boost::scoped_ptr

    (1)scoped_ptr 没有 release 函数

    (2)没有重载 operator=,不会导致所有权转移,但无法赋值,拷贝智能指针。

    boost::shared_ptr
    (1)专门用于共享所有权,内部使用引用计数use_count() ,因此可以支持复制、参数传递等,也是用于管理单个堆内存对象的

    (2)同样没有release() 函数。

    boost::scoped_array

    (1)用于管理动态数组

    (2) boost::scoped_array<Simple> my_memory(new Simple[2]); // 使用内存数组来初始化

    (3)scoped_ptr 没有重载 operator*

    (4)没有重载 operator=

    ⑤boost::shared_array

    内部使用了引用计数,可以复制,通过参数来传递。

    ⑥boost::weak_ptr

    是专门为 boost::shared_ptr 而准备的,boost::weak_ptr 只对 boost::shared_ptr 进行引用,而不改变其引用计数,
    当被观察的 boost::shared_ptr 失效后,相应的 boost::weak_ptr 也相应失效

    ⑦boost::intrusive_ptr

    这是一种插入式的智能指针,内部不含有引用计数,需要程序员自己加入引用计数。

    智能指针总结:

    1、在可以使用 boost 库的场合下,拒绝使用 std::auto_ptr,因为其不仅不符合 C++ 编程思想,而且极容易出错[2]。

    2、在确定对象无需共享的情况下,使用 boost::scoped_ptr(当然动态数组使用 boost::scoped_array)。

    3、在对象需要共享的情况下,使用 boost::shared_ptr(当然动态数组使用 boost::shared_array)。

    4、在需要访问 boost::shared_ptr 对象,而又不想改变其引用计数的情况下,使用 boost::weak_ptr,一般常用于软件框架设计中。

    5、最后一点,也是要求最苛刻一点:在你的代码中,不要出现 delete 关键字(或 C 语言的 free 函数),因为可以用智能指针去管理。

  • 相关阅读:
    Leetcode Reverse Words in a String
    topcoder SRM 619 DIV2 GoodCompanyDivTwo
    topcoder SRM 618 DIV2 MovingRooksDiv2
    topcoder SRM 618 DIV2 WritingWords
    topcoder SRM 618 DIV2 LongWordsDiv2
    Zepto Code Rush 2014 A. Feed with Candy
    Zepto Code Rush 2014 B
    Codeforces Round #245 (Div. 2) B
    Codeforces Round #245 (Div. 2) A
    Codeforces Round #247 (Div. 2) B
  • 原文地址:https://www.cnblogs.com/blogs-of-lxl/p/6481045.html
Copyright © 2011-2022 走看看