C++的语义类型和弱引用

来源:互联网 发布:java 有序集合 编辑:程序博客网 时间:2024/05/18 01:05
C++中存在两种语义:值语义(value sematics)和对象语义(object sematic),对象语义也可以叫做引用语义(reference sematics)。
值语义,指的是对象的拷贝与原对象无关,就像拷贝int一样,C++的常用类型数据等都是值语义。
对象语义,指的是面向对象意义下的对象,是禁止拷贝的。

在设计一个类的时候该类是否可以被拷贝(即具备拷贝构造函数),取决于拷贝后的语义是否成立,比如一个Thread类,拷贝后系统中并不会启动另外一个线程,所以拷贝是禁止的。
同样类似于Employee雇员类也是。

C++最大的问题是内存越界,没有自动垃圾内存回收机制,当越界时,程序就会core dump,这是最头疼的。很多情况都是由悬挂指针(野指针)引起的。

在多线程程序中,一个对象如果被多个线程访问,一般使用shared_ptr,通过引用计数来保证对象不被错误的释放导致其他线程访问出现问题。
但这种引用计数解决不了循环引用的问题,有如下代码:
父类Parent和子类Child,均有指向对方的指针
Class Parent{public:    // ...private:    shared_ptr<Child> m_child;}Class Child{public:    // ...private:    shared_ptr<Parent> m_parent;}
这样由于两个类之间互相引用,它们的计数都是1,最后谁也不会被释放,就导致了内存泄漏。

一般解除循环引用有三种办法:
1.手动释放
2.如果Parent拥有Child,即Parent的生存期比Child大,那么Child就使用一个普通的指针
3.使用弱引用的智能指针打破循环引用。

强引用:当至少有一个强引用时,对象就不能被释放。shared_ptr就是如此。
弱引用:它仅仅是对象存在时候的引用,当对象不存在时弱引用能够检测到,从而避免非法访问,弱引用也不会修改对象的引用计数。
template<typename T> class weak_ptr{    public:        template <typename Y>        weak_ptr(const shared_ptr<Y>& r);        weak_ptr(const weak_ptr& r);        ~weak_ptr();        T* get() const;         bool expired() const;         shared_ptr<T> lock() const;};
定义变量:
shared_ptr<T>  t(new T);
weak_ptr<T> ptr(t); // t为一个T对象 
则当t被销毁时,ptr 被自动置为无效。使用方法如下:
if ( shard_ptr<T>  safePtr  = ptr.lock() )  safePtr->Fun();
weak_ptr必须从一个boost::share_ptr或另一个boost::weak_ptr转换而来,这也说明,进行该对象的内存管理的是那个强引用的boost::share_ptr。boost::weak_ptr只是提供了对管理对象的一个访问手段。
弱引用指针可以有效的解除循环引用,但这种方式必须在程序员能预见会出现循环引用的情况下才能使用,也可以是说这个仅仅是一种编译期的解决方案,如果程序在运行过程中出现了循环引用,还是会造成内存泄漏的。