各类ptr

auto_ptr:它允许程序员创建一个指向某种资源的指针对象,当该对象离开它的作用域时,它所指向的资源也会被自动释放。

在原本的C++中,new和delete必须配对使用,然而给每个异常处理分支添加delete是一件很麻烦的事。auto_ptr就是用来干这事的,它无需显式调用delete。

对auto_ptr的赋值和拷贝会导致原来的auto_ptr变为NULL,从而无效化。

unique_ptr:auto_ptr是全局唯一的,且不采用引用计数管理,因此,赋值和拷贝都是不必要的,且会造成混淆。(尤其拷贝会导致原来的auto_ptr变为NULL,这个还能叫做拷贝吗?)因此,auto_ptr在后续标准中,不再推荐使用,而是用unique_ptr替代。unique_ptr默认不支持赋值和拷贝,确需使用,要与std::move配合方可。否则会编译出错。

unique_ptr早先在boost库中的时候,也叫做scoped_ptr。

shared_ptr:为多个拥有者管理内存中对象的生命周期而设计的。在你初始化一个shared_ptr后,你可以复制它,把函数参数的值递给它,并把它分配给其它shared_ptr实例。所有实例指向同一个对象,并共享访问一个“控制块”,即每当一个新的shared_ptr被添加时,递增和递减引用计数,超出范围,则复位。当引用计数到达零时,控制块删除内存资源和自身。

weak_ptr:如果对象A中有对象B的shared_ptr,而对象B中又有对象A的shared_ptr,那么就会出现循环引用的情况。这时可以使用weak_ptr。两者的区别在于新建shared_ptr会增加引用计数,而weak_ptr不会。

上述指针还可以自己定义deleter:

void close_file(std::FILE* fp) { std::fclose(fp); }
std::unique_ptr<std::FILE, decltype(&close_file)> fp(std::fopen("demo.txt", "r"),&close_file);

上面的close_file就是自定义的deleter,用来进行特殊的析构。

上述ptr不仅可以保存对象的指针,还可以保存数组指针:

shared_ptr<double[]> p2( new double[n] );

此外ptr的声明方式也有两种(以unique_ptr为例):

  • 方法1:std::unique_ptr<int>(new int(1));

  • 方法2:std::make_unique<int>(1);

从实现来看,这些智能指针除了需要new对象之外,还需要new一个用于维护对象引用计数的控制块,因此第2种方法一次性分配的效率会比较高。

一般来说,make_XXX在标准库中,通常都带有new对象和相关控制结构的操作,除了上述的make_unique之外,类似的还有make_pair等。


shared_ptr既然号称共享,那自然有一定的共享规则在:

shared_ptr<int> sp1(new int(10));
shared_ptr<int> sp2(sp1), sp3;
sp3 = sp1;
//一个典型的错误用法
shared_ptr<int> sp4(sp1.get());
cout << sp1.use_count() << " " << sp2.use_count() << " "
<< sp3.use_count() << " " << sp4.use_count() << endl;
//输出 3 3 3 1

sp1,sp2,sp3是相互关联的共享指针,共同控制所指内存的生存期,sp4虽然指向同样的内存,却是与sp1,sp2,sp3独立的,sp4按自己的引用计数来关联内存的释放。


auto p = std::make_unique<XXX>();
void f(XXX*);
f(p); // error
f(p.get()); // OK

虽然,类似p->YYY()的用法和普通指针一致,但是作为f函数参数的时候,就不行了。


参考:

https://mp.weixin.qq.com/s/32aeGOPaySjTmyKcjFKgYA

窥见C++11智能指针

https://www.cnblogs.com/wangkeqin/p/9351191.html

C++内存管理之shared_ptr

https://blog.csdn.net/River_Lethe/article/details/78734879

shared_ptr的使用和陷阱

decltype

和auto的用法类似,auto不仅要推导类型,还要定义变量,而decltype则只进行类型推导。

int add(int x,int y){return x+y;
}
int main(){double i=0;decltype(i) a; // doubledecltype(add()) b; //int 注意括号。不带括号就是函数指针了。
}

参考:

https://www.cnblogs.com/npbool/p/3433360.html

C++11初探:类型推导,auto和decltype

类型转换

static_cast:基本等同于C语言的强制类型转换,只有很小的差异。

dynamic_cast:主要用于类层次间的上行转换和下行转换。

const_cast:用于修改类型的const或volatile属性。

reinterpret_cast:它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。

上面4个算是C++的基本类型变换。除此之外还有一些变种。

  • 和shared_ptr配套的类型变换:

static_pointer_cast:Static cast of shared_ptr

dynamic_pointer_cast:Dynamic cast of shared_ptr

const_pointer_cast:Const cast of shared_ptr

  • dynamic_cast的改进版(主要是增加了一些断言或者异常处理):
template <class Derived, class Base>
inline Derived polymorphic_cast(Base* x);
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
// Returns: dynamic_cast<Derived>(x)template <class Derived, class Base>
inline Derived polymorphic_downcast(Base* x);
// Effects: assert( dynamic_cast<Derived>(x) == x );
// Returns: static_cast<Derived>(x)template <class Derived, class Base>
inline auto polymorphic_pointer_cast(Base x);
// Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
// Returns: dynamic_pointer_cast<Derived>(x)template <class Derived, class Base>
inline auto polymorphic_pointer_downcast(Base x);
// Effects: assert( dynamic_pointer_cast<Derived>(x) == x );
// Returns: static_pointer_cast<Derived>(x)

参考:

https://www.cnblogs.com/chenyangchun/p/6795923.html

C++强制类型转换:static_cast、dynamic_cast、const_cast、reinterpret_cast

std::bind & std::placeholders

void f(int n1, int n2, int n3, const int& n4, int n5)
{std::cout << n1 << ' ' << n2 << ' ' << n3 << ' ' << n4 << ' ' << n5 << '\n';
}auto f2 = std::bind(f, _3, std::bind(g, _3), _3, 4, 5);
f2(10, 11, 12); // 进行到 f(12, g(12), 12, 4, 5); 的调用

不定参数

int sum(int count, ...)
{va_list vl;int sum = 0;va_start(vl, count);for (int i = 0; i < count; ++i){sum += va_arg(vl, int);}va_end(vl);return sum;
}

上面是C风格的变参函数,主要依赖了va_xx系列函数。

template<typename T>
void Append(Optimizer::Optimizations& optimizations, T&& optimization)
{optimizations.emplace_back(new T(optimization));
};template<typename Front, typename... Others>
void Append(Optimizer::Optimizations& optimizations, Front&& front, Others&&... others)
{Append<Front>(optimizations, std::forward<Front>(front));Append<Others...>(optimizations, std::forward<Others>(others)...);
};template<typename... Args>
Optimizer::Optimizations MakeOptimizations(Args&&... args)
{Optimizer::Optimizations optimizations;Append(optimizations, std::forward<Args>(args)...);return optimizations;
}

上面是C++风格的变参函数。它主要采用了Parameter pack技术,简单的说就是递归的模板展开。

以上面的函数为例:

1.首先使用第2个模板函数展开函数。

2.在第2个模板函数中调用第1个模板函数,而第1个模板函数不是变参函数,相当于是递归的结尾。

std::tuple、std::bind等的实现都借助了Parameter pack。

在C++17中,还提出一个叫做fold expression的技术。

template<typename ...Args>
int sum(Args&&... args) {//    return (args + ... + 1 * 2); // Error: operator with precedence below castreturn (args + ... + (1 * 2)); // OK
}

上述函数是一个对+运算符的fold expression。

参考:

https://www.jianshu.com/p/d22904f30930

C++11新特性–不定参数模板与std::tuple、std::bind实现原理

特化(traits)

template<class T1, class T2>      // 普通版本,有两个模板参数
class B { ..... };template<class T2>         // 偏特化版本,指定其中一个参数,即指定了部分类型
class B<int , T2> { ..... };// 当实例化时的第一个参数为int 则会优先调用这个版本

偏特化的条件:

1.必须有一个主模板。

2.模板类型被部分明确化。

相应的,如果模板参数全被指定,则为全特化

对主版本模板类、全特化类、偏特化类的调用优先级从高到低进行排序是:全特化类>偏特化类>主版本模板类。

traits一方面,在面对不同的输入类时,能找到合适的返回型别;另一方面,当型别对应有不同的实现函数的时候,能起到一个提取型别然后分流的作用。

标准库已经内置了一些常见的traits操作,例如std::pointer_traits,该模板可返回迭代器指向对象的型别。

参考:

https://www.cnblogs.com/yyehl/p/7253254.html

C++ 模板偏特化-来自STL的思考

https://www.cnblogs.com/mangoyuan/p/6446046.html

C++ traits技术浅谈

typename

vector<T>::size_type可能有三种解释:

  • 静态数据成员

  • 静态成员函数

  • 嵌套类型

前两者比较好区分,函数名后一般有括号。但是嵌套类型就不好区分了,因此需要用typename关键字指定之。

参考:

https://blog.csdn.net/zhangxiao93/article/details/50569924

C++ typedef typename作用

typeid

typeid可用于打印类型名称。这里的类型可以是固定类型,也可以是模板类型。

cout << typeid(int).name() << typeid(T).name() << endl;

C/C++编程心得(三)相关推荐

  1. 服务器端编程心得(三)—— 一个服务器程序的架构介绍

    本文将介绍我曾经做过的一个项目的服务器架构和服务器编程的一些重要细节. 一.程序运行环境 操作系统:centos 7.0 编译器:gcc/g++ 4.8.3     cmake 2.8.11 mysq ...

  2. 脑残式网络编程入门(三):HTTP协议必知必会的一些知识

    为什么80%的码农都做不了架构师?>>>    本文原作者:"竹千代",原文由"玉刚说"写作平台提供写作赞助,原文版权归"玉刚说&q ...

  3. IME输入法编程心得

     原文链接: IME输入法编程心得 posted @ 2012-11-30 00:42 from [FreedomShe] 自然语言处理的输入法作业成品没有做出来,但不想再在蛋疼的Win32上面耗 ...

  4. 服务器端编程心得(七)——开源一款即时通讯软件的源码

    服务器端编程心得(七)--开源一款即时通讯软件的源码 2017年04月06日 22:57:01 analogous_love 阅读数:30222更多 所属专栏: 高性能服务器编程实现细节详解 版权声明 ...

  5. c语言对编程对作用,c语言编程心得体会

    c语言编程心得体会 c语言是在国内外广泛使用的一种计算机语言.以下是小编整理的c语言编程心得体会,欢迎大家阅读! c语言编程心得体会1 说到我学习c语言时,真是用千言万语呀!记得刚开始学的时候,我的c ...

  6. linux系统编程心得体会范文大全,编程心得体会范文

    编程就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到相应结果的过程.下面是学习啦带来的编程的心得体会范文,欢迎欣赏. C语言是在国内外广泛使用的一种计算机语言.其语言功能丰富. ...

  7. /* * 编程第三题(20分) 打印所有的水仙花数。所谓水仙花数是指一个三位数,其各位数字的立方和等于该数本身。(例153=1*1*1+3*3*3+5*5*5) */

    题目: /* 编程第三题(20分) 打印所有的水仙花数.所谓水仙花数是指一个三位数,其各位数字的立方和等于该数本身.(例153=111+333+555) */ 我是用java做的 public cla ...

  8. UART0串口编程(三):中断方式的串口编程;用中断编写发送函数

    UART0串口编程(三) 一:中断方式的串口编程 1.用中断方式编写串口程序由那几部分组成 2.硬件上的支持 1>UART0 发送FIFO缓冲区 A.UART0含有1个16字节的发送FIFO缓冲 ...

  9. QML和C++混合编程--(三)

    文章目录 QML和C++混合编程--(三)之属性绑定 简介: 示例: 代码过程: 总结: QML和C++混合编程–(三)之属性绑定 简介: 属性绑定是QML的一个强有力的特性,它使得各种类型的值被自动 ...

  10. .Net 3.5 Remoting编程入门三

    VS2008 .Net 3.5 Remoting编程入门三 信道 什么是信道?信道有哪些类型呢? 信道顾名思意就是通信的通道.就想那些宣传标语说的,"要想富,先修路!".同理,要学 ...

最新文章

  1. python读取写入文件_Python文件读写保存操作
  2. 租房界的php,php实现出租房数据管理及搜索页面
  3. .net pdf转图片_pdf2image类库实现批量pdf转图片
  4. vuex 的模块化+命名空间
  5. 八戒科技服务技术负责人鸿鹄真人:做好技术负责人的4个关键特质
  6. [转载] RGB与16进制色互转
  7. 微信 小程序 python 渲染_干货 | 微信小程序自动化测试最佳实践(附 Python 源码)...
  8. yum与apt-get的区别以及两者更新源(阿里/网易【163】)
  9. 算法导论 9.1-1 “给出算法,在给定的比较次数(n+向上取整(lgn)-2)内,一定能找出第二小的元素。提示:也找出最小元素。”...
  10. C语言入门题库——求2+22+222+......+22222的值
  11. 基于电商常识图谱的知识表示与应用
  12. python发音小程序
  13. pyhanlp 共性分析与短语提取内容详解
  14. APP——功耗测试(耗电测试)——基础知识
  15. STM32F103ZET(基于秉火开发板)+Cubemx(F1 V1.60库)+RTC(修复官方例程日期不更新bug)
  16. Android高手进阶教程(一)-------Android常用名令集锦(图文并茂)!
  17. 191119_01 网站集成QQ第三方登录
  18. 顶尖程序员 VS 普通程序员
  19. 读书笔记:《眨眼之间》
  20. Android--实现类似支付宝的功能拖拽、增删

热门文章

  1. 计算机应用在开始栏显示乱码,大神解决win10系统应用程序和开始菜单出现乱码的详细方案...
  2. java instanceof 继承_继承_instanceOf的使用
  3. delphi添加类文件_SpringBoot攻略三、配置文件说明
  4. 台式电脑如何截屏_如何选购台式电脑显卡?小白装机通俗易懂的独立显卡知识指南...
  5. 非平坦结构元matlab,基于MATLAB的巴特沃思型数字滤波器设计.doc
  6. oracle ora 16014,ORACLE ORA-16014+ORA-00312 数据库在线重做日志没有归档
  7. 全选反选JavaScript实现
  8. element ui表单验证
  9. openresty火焰图安装
  10. 联发科Helio P35处理器曝光:10GB运存