C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).
6870 ワード
目次 C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector). auto_ptr scoped_ptr ptr_vector
C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).
前言
最近muduoの非同期ログをもう1つ書いて多くのスマートポインタに触れたが、boostライブラリを使うつもりはなく、1つ型を作って使うしかなかった.
インテリジェントポインタ自体はスタック上に作成するオブジェクトであり、構築時にスタック上のリソースを割り当て、構築時にリソースを解放することで、スタック上のデータリソースの漏洩を回避することができる.同時にリロードする->演算子と*演算子は、裸のポインタのような操作を実現する.
いくつかのローカルスマートポインタオブジェクトの実装コードを見てみましょう.
auto_ptr
auto_ptrの特徴:コピー構造関数を実現し、=演算子を再ロードし、->、*演算子を実現し、通常のポインタのように使用できるようにするとともにrelease()とreset()法により安全な転送使用権を実現する.
テストコード:
scoped_ptr
これはboostライブラリの中のもので、auto_とptrは正反対:コピー構造と=リロードをすべてプライベートに構成する、所有権の移転を許さない目的を達成した.
ptr_vector
これもboostの中のもので、もし私たちがオブジェクトポインタをvectorの中に置くだけで、容器が析出するときは自分で開いたポインタを格納する空間を析出するが、ポインタ自体が指す空間を析出することはなく、この容器がある.
テストコード:
本文は主にスマートポインタの本質を紹介し、二つの簡単なスマートポインタの実現と一つのポインタ容器の実現を紹介した.
実は今auto_ptrはあまり使われていませんが、元のポインタを処理していないと、移行後、元のポインタが空になり、誰かが使用すると問題になります.vectorにも多くの問題がありますpop_back()は空の容器で、vectorの中で同じようにします--size、この时容器の大きさは0から无限に大きくなって、结果は予想できません、.本例では、このような場合を処理する.pop_back()空のvectorは何もしません.しかしvectorの使い方にはこだわりがある.そうしないと問題になりやすい.
転載先:https://www.cnblogs.com/ailumiyana/p/9451761.html
C++インテリジェントポインタ、ポインタ容器の原理と簡単な実現(auto_ptr、scoped_ptr、ptr_vector).
前言
最近muduoの非同期ログをもう1つ書いて多くのスマートポインタに触れたが、boostライブラリを使うつもりはなく、1つ型を作って使うしかなかった.
.
インテリジェントポインタ自体はスタック上に作成するオブジェクトであり、構築時にスタック上のリソースを割り当て、構築時にリソースを解放することで、スタック上のデータリソースの漏洩を回避することができる.同時にリロードする->演算子と*演算子は、裸のポインタのような操作を実現する.
いくつかのローカルスマートポインタオブジェクトの実装コードを見てみましょう.
auto_ptr
auto_ptrの特徴:コピー構造関数を実現し、=演算子を再ロードし、->、*演算子を実現し、通常のポインタのように使用できるようにするとともにrelease()とreset()法により安全な転送使用権を実現する.
#ifndef _AUTO_PTR_HH
#define _AUTO_PTR_HH
template
class auto_ptr{
public:
explicit auto_ptr(T* p = 0):m_ptr(p){printf("1
");
}
auto_ptr(auto_ptr& obj):m_ptr(obj.release()){printf("2
");
}
auto_ptr& operator=(auto_ptr& obj){printf("3
");
reset(obj.release());
return *this;
}
~auto_ptr(){printf("4
");
delete m_ptr;
}
T* release(){
T* tmp = m_ptr;
m_ptr = 0;
return tmp;
}
void reset(T* p){
if(m_ptr != p)
delete m_ptr;
m_ptr = p;
}
T* get() const {
return m_ptr;
}
T* operator->(){
return get();
}
T& operator*(){
return *get();
}
private:
T* m_ptr;
};
#endif
テストコード:
#include "ScopePtr.hh"
#include "auto_ptr.hh"
#include
class NonCopyable
{
protected: // ,
NonCopyable() {printf("Nocopy Constroctr
");}
~NonCopyable() {printf("~Nocopy DeConstroctr
");}
private:
NonCopyable(const NonCopyable &);
const NonCopyable &operator=(const NonCopyable &);
};
class Test// : private NonCopyable{
{public:
Test(){printf("Constroctr
");}
~Test(){printf("~DeConstroctr
");}
};
int main(){
//scoped_ptr st(new Test);
auto_ptr ap1(new Test);
auto_ptr ap2(new Test);
auto_ptr ap3(ap2);
ap2 = ap3;
getchar();
return 0;
}
Constroctr
1
Constroctr
1
2
3
4
4
~DeConstroctr
4
~DeConstroctr
scoped_ptr
これはboostライブラリの中のもので、auto_とptrは正反対:コピー構造と=リロードをすべてプライベートに構成する、所有権の移転を許さない目的を達成した.
#ifndef _SCOPE_PTR_HH
#define _SCOPE_PTR_HH
// scoped_ptr mimics a built-in pointer except that it guarantees deletion
// of the object pointed to, either on destruction of the scoped_ptr or via
// an explicit reset(). scoped_ptr is a simple solution for simple needs;
// use shared_ptr or std::auto_ptr if your needs are more complex.
/*
scoped_ptr 。
*/
template
class scoped_ptr
{
public:
scoped_ptr(T *p = 0) :m_ptr(p) {
}
~scoped_ptr(){
delete m_ptr;
}
T&operator*() const {
return *m_ptr;
}
T*operator->() const {
return m_ptr;
}
void reset(T *p)//
{
if (p != m_ptr && m_ptr != 0)
delete m_ptr;
m_ptr = p;
}
T* get(){
return m_ptr;
}
private://
// ,
scoped_ptr(const scoped_ptr &y);
scoped_ptr operator=(const scoped_ptr &);
void operator==(scoped_ptr const &) const;
void operator!=(scoped_ptr const &) const;
T* m_ptr;
};
#endif
ptr_vector
これもboostの中のもので、もし私たちがオブジェクトポインタをvectorの中に置くだけで、容器が析出するときは自分で開いたポインタを格納する空間を析出するが、ポインタ自体が指す空間を析出することはなく、この容器がある.
#ifndef _PTR_VECTOR_HH
#define _PTR_VECTOR_HH
#include "auto_ptr.hh"
#include
template
class ptr_vector : public std::vector{
public:
~ptr_vector(){
clear();
}
void clear(){
typename std::vector::iterator it;
for(it = std::vector::begin(); it != std::vector::end(); ++it){
delete *it;// .
}
/*
for(size_t i = 0; i < std::vector::size(); ++i){
delete std::vector::back();
}*/
std::vector::clear(); // .
}
typename std::vector::iterator erase(typename std::vector::iterator it){
if(it >= std::vector::begin() && it < std::vector::end()){
delete *it;
std::vector::erase(it);
}
}
void pop_back(){
if(std::vector::size() > 0){
delete std::vector::back();
std::vector::pop_back();
}
}
void push_back(T* const &v){
auto_ptr ap(v);
std::vector::push_back(v);
ap.release();
}
void push_back(auto_ptr &v){
std::vector::push_back(v.get());
v.release();
}
};
#endif
テストコード:
class Test// : private NonCopyable{
{public:
Test(int a = 99):a(a){printf("Constroctr
");}
~Test(){printf("~DeConstroctr
");}
int get(){return a;}
private:
int a;
};
int main(){
auto_ptr ap1(new Test(0));
auto_ptr ap2(new Test(1));
auto_ptr ap3(new Test(2));
printf("%d
", ap1->get());
ptr_vector apv;
apv.push_back(ap1);
apv.push_back(ap2);
apv.push_back(ap3);
printf("%d %lu
", apv.front()->get(),apv.size());
/*
apv.pop_back();
printf("%lu
", apv.size());
apv.pop_back();
printf("%lu
", apv.size());
apv.pop_back();
printf("%lu
", apv.size());
*/
apv.pop_back();
printf("%lu
", apv.size());
ptr_vector::iterator it = apv.begin();
apv.erase(it);
printf("%lu
", apv.size());
getchar();
return 0;
}
Constroctr
Constroctr
Constroctr
0
0 3
~DeConstroctr
2
~DeConstroctr
1
~DeConstroctr
本文は主にスマートポインタの本質を紹介し、二つの簡単なスマートポインタの実現と一つのポインタ容器の実現を紹介した.
実は今auto_ptrはあまり使われていませんが、元のポインタを処理していないと、移行後、元のポインタが空になり、誰かが使用すると問題になります.vectorにも多くの問題がありますpop_back()は空の容器で、vectorの中で同じようにします--size、この时容器の大きさは0から无限に大きくなって、结果は予想できません、.本例では、このような場合を処理する.pop_back()空のvectorは何もしません.しかしvectorの使い方にはこだわりがある.そうしないと問題になりやすい.
転載先:https://www.cnblogs.com/ailumiyana/p/9451761.html