最近尝试写一些基本的C++泛型组件,其实很多都是boost里已经有了,但是还是喜欢自己再写一下, 原因有三:
1. boost太庞大,拿来学习不错,但是一般不会直接在项目中把它import进来。
2. C++11也挺不错,但是现在工作还是以VS2008为主,所以这些新特性暂时用不上。
3. 重复造轮子才能更好的理解轮子背后的原理,以后才能更好的操作轮子。
看一些库时发现仅指针一项就有挺多封装, 思考为什么需要智能指针?
通过智能指针可以以RAII的方式管理对象, 编写异常安全的代码; 原始的指针没有标明对象所有权的情况, 对象是你单独拥有的?还是你和别人共享对象, 但是你也参与管理? 还是你只是使用对象,但是没有所有权? 智能指针很好的解决了这些问题。
下面是一些常见的智能指针封装形式:
std::auto_ptr
基于所有权的智能指针,每次赋值或是拷贝构造都是所有权的转移,所以不能放到标准容器中。
unique_ptr
同样是基于所有权的智能指针,不支持赋值或是拷贝构造,但是因为C++11 Move语义和右值引用的支持,可以通过Move的方法放置到容器中。
proxy_ptr
仅是原始指针的封装代理,和普通指针没有什么区别, 不参与对象生命周期的管理。
ref_ptr (intrusive_ptr)
入侵式的引用计数智能指针,对象本身具有引用计数功能, 外部指针通过对象的引用计数管理该对象的生命周期。很多框架和库都是基于这种方式, 典型COM组件开发中的CComPtr就是这种类型的指针。
shared_ptr
非入侵式的引用计数智能指针,对象本身不需要计数功能,外部指针在创建对象时会自己创建计数功能并与对象绑定。这种方式使用起来非常方便,但是如果使用不当也会有很多问题, 具体参见shared_ptr四宗罪
weak_ptr
一般配合share_ptr一起使用, 因为weak_ptr本身不参与对象引用计数的管理,但是它能查询所引用的对象是否还有效, 所以通过weak_ptr可以解决循环引用的问题。
在写泛型代码的过程中,会有对程序失去控制的感觉,比如下面的代码:
我们用C写代码时可以明确知道每行代码最终汇编执行时的情况。
用经典C++(面向对象)写代码时, 如果C++基础扎实,也可以大概知道背后的汇编代码, 无非是多些构造,拷贝,赋值,析构,多态等。
但是用现代C++(面向对象+泛型), 你却很难知道最终展开后的汇编代码情况, 因为泛型与对方传的类型密切相关, 可能你一不小心,对象就被拷贝了N多份,而你还浑然不知。
越抽象的东西离底层机器就越遥远, C++隔着复杂的编译器, Java/C#隔着虚拟机, 脚本语言隔着解释器, 这就是高级语言的代价。
看一些开源的东西,越来越觉得博客没啥好写了,基础的东西大家都懂, 高级的东西我也不懂,不知道以前为什么有勇气写这么多东西 ^_^
附上最近模仿的一点东西: MySLib
1. boost太庞大,拿来学习不错,但是一般不会直接在项目中把它import进来。
2. C++11也挺不错,但是现在工作还是以VS2008为主,所以这些新特性暂时用不上。
3. 重复造轮子才能更好的理解轮子背后的原理,以后才能更好的操作轮子。
看一些库时发现仅指针一项就有挺多封装, 思考为什么需要智能指针?
通过智能指针可以以RAII的方式管理对象, 编写异常安全的代码; 原始的指针没有标明对象所有权的情况, 对象是你单独拥有的?还是你和别人共享对象, 但是你也参与管理? 还是你只是使用对象,但是没有所有权? 智能指针很好的解决了这些问题。
下面是一些常见的智能指针封装形式:
std::auto_ptr
基于所有权的智能指针,每次赋值或是拷贝构造都是所有权的转移,所以不能放到标准容器中。
unique_ptr
同样是基于所有权的智能指针,不支持赋值或是拷贝构造,但是因为C++11 Move语义和右值引用的支持,可以通过Move的方法放置到容器中。
proxy_ptr
仅是原始指针的封装代理,和普通指针没有什么区别, 不参与对象生命周期的管理。
ref_ptr (intrusive_ptr)
入侵式的引用计数智能指针,对象本身具有引用计数功能, 外部指针通过对象的引用计数管理该对象的生命周期。很多框架和库都是基于这种方式, 典型COM组件开发中的CComPtr就是这种类型的指针。
shared_ptr
非入侵式的引用计数智能指针,对象本身不需要计数功能,外部指针在创建对象时会自己创建计数功能并与对象绑定。这种方式使用起来非常方便,但是如果使用不当也会有很多问题, 具体参见shared_ptr四宗罪
weak_ptr
一般配合share_ptr一起使用, 因为weak_ptr本身不参与对象引用计数的管理,但是它能查询所引用的对象是否还有效, 所以通过weak_ptr可以解决循环引用的问题。
在写泛型代码的过程中,会有对程序失去控制的感觉,比如下面的代码:
//C++ 11
class bigclass {};
void fun(bigclass& b){}
int main()
{
bigclass c;
std::thread t(&fun, c);
t.join();
return 0;
}
你知道上面的c对象被拷贝了多少次吗? 如果改成std::ref(c)后呢?class bigclass {};
void fun(bigclass& b){}
int main()
{
bigclass c;
std::thread t(&fun, c);
t.join();
return 0;
}
我们用C写代码时可以明确知道每行代码最终汇编执行时的情况。
用经典C++(面向对象)写代码时, 如果C++基础扎实,也可以大概知道背后的汇编代码, 无非是多些构造,拷贝,赋值,析构,多态等。
但是用现代C++(面向对象+泛型), 你却很难知道最终展开后的汇编代码情况, 因为泛型与对方传的类型密切相关, 可能你一不小心,对象就被拷贝了N多份,而你还浑然不知。
越抽象的东西离底层机器就越遥远, C++隔着复杂的编译器, Java/C#隔着虚拟机, 脚本语言隔着解释器, 这就是高级语言的代价。
看一些开源的东西,越来越觉得博客没啥好写了,基础的东西大家都懂, 高级的东西我也不懂,不知道以前为什么有勇气写这么多东西 ^_^
附上最近模仿的一点东西: MySLib