其实,本人只是想不懂这程序为啥会内存泄漏,本人单步过了,知道是哪一句导致的,但是想不懂。
// fg.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include<string> #include<iostream> using namespace std; template<class T> class share { public: share():point(0),pcount(NULL){} share(T* p1) { pcount=new int(0); point = p1; if (pcount == NULL) { pcount = new int(1); } } ~share() { if(--(*pcount) == 0) { delete point; delete pcount; pcount = NULL; cout << "begin to delete share" << endl; point = NULL; } } share(share& t2) { point = t2.point; (*t2.pcount)++; pcount = t2.pcount; } share& operator =(share& t2) { if (--(*pcount) == 0) { delete point; } point = t2.point; t2.(*pcount)++; cout<<t2.(*pcount)<<endl; cout<<*(t2.pcount)<<endl; pcount = t2.pcount; return *this; } T* operator ->() { return point; } private: T* point; int* pcount; //应该用boost::detail::atomic_count }; class A { public: A() { n = 0; } int n; char v[4]; }; int main() { share<A> sp(new(std::nothrow) A()); sp->n = 10; cout << "sp->n is :" << sp->n << endl; share<A> sp2 = sp; sp2->n = 20; cout << "sp->n is :" << sp2->n << endl; return 0; }
在初始化时候本人想采用的是
share():point(0),pcount( new int(0)){}
这种方式初始化,但是pcount每次都初始化失败,为空的。另外在析构函数这里
~share() { if(--(*pcount) == 0) { delete point; delete pcount; pcount = NULL; cout << "begin to delete share" << endl; point = NULL; } }
这样就会奔溃,程序已经执行完了,明显是内存泄漏奔溃,但是把单步后定位在
if(--(*pcount) == 0)
把
if(--(*pcount) == 0)
改成
if((*pcount) == 0)
这样就不会奔溃,纳闷了,假设不–,下面的就没办法执行,就没有释放,程序就不奔溃。
解决方案
10
count 应该和指针一起绑定。
你的count 属于每一个share,而不属于每一个 指针。
你的count 属于每一个share,而不属于每一个 指针。
30
// 改了一下, 说几点: // 1. 使用c++11的一些特性, 刚开始学者一开始就学好 // 2. 使用类的构造初始化列表构造对象是一个好习惯 // 3. 复制构造函数的参数是const T&, 不要忘了 // 4. 既然提供了默认构造函数使指针为空, 为什么在析构函数里面以至其他函数都不判断一下? // 5. c++允许手动调用析构/构造函数, 让operator=写法便利了不少 // 6. 既然知道有std::nothrow 那一步判断能否指针为空不明所以 // 7. 注释上写了最好使用原子操作, 为什么不写进模板参数, 这样本人单线程使用就不用原子操作了 #include <string> #include <iostream> template<class T, class U> class share { public: share() :point(nullptr), pcount(nullptr) {} share(T* p) : point(p), pcount(new U(1)) { } ~share() { if (!this->pcount) return; if (!--(*pcount)) { delete point; delete pcount; //cout << "begin to delete share" << endl; } } share(const share& t2) noexcept : point(t2.point), pcount(t2.pcount) { if (this->pcount) (*this->pcount)++; } share(share&& t2) noexcept : point(t2.point), pcount(t2.pcount) { t2.point = nullptr; t2.pcount = nullptr; } share& operator =(share&& t2) noexcept { this->share::~share(); this->share::share(std::move(t2)); return *this; } share& operator =(const share& t2) noexcept { this->share::~share(); this->share::share(t2); return *this; } T* operator ->() noexcept { return point; } private: T* point; U* pcount; }; class A { public: A() { n = 0; } int n; char v[4]; }; int main() { share<A, int> sp(new(std::nothrow) A()); sp->n = 10; std::cout << "sp->n is :" << sp->n << std::endl; share<A, int> sp2 = sp; sp2->n = 20; std::cout << "sp->n is :" << sp2->n << std::endl; return 0; }
10
原地构造要用
new(this) share(t1);
this->share::share(t1); 是不行的。
new(this) share(t1);
this->share::share(t1); 是不行的。