使用STL时的引用对象 [英] reference object when using STL

查看:90
本文介绍了使用STL时的引用对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好专家!!


这个类模板和main工作完全正常。

我有这个名为Handle的类模板,它有一个声明为T的指针*

身体;

正如你所看到的,我在课堂模板中有一个参考计数器,所以我知道

我有多少参考身体。在我的情况下,它是整数包装器

类是正文。

此模板适用于许多不同类型。

一个我使用的名为Integer,是int的包装器。代码

这个不包括

因为它没有添加任何进一步的信息。

在底部我有一个主要的。

在main中我可以调用独立函数addNodeToSTL以及更多的

将节点添加到名为myList1的STL列表容器中。

这里是将节点添加到STL列表容器的独立函数。

void addNodeToSTL(list< handle_t> * myList)

{

handle_t myh(new Integer(getValue(" Ange vardet som du vill lagga in i

listan / listorna:")));

myList-> push_front(myh );

}


这个handle_t是typedef

typedef Handle< Integer> handle_t;

现在我的问题是当我向STL容器添加节点时,在我的情况下实际上是一个

的参考对象。


它是STL内部的东西还是我的类模板Handle。?


模板< class T>

class Handle

{

public:

Handle()

{

body = new T(0);

ref_count = new int(1);

}


句柄(T * body_ptr)//构造函数

{

body = body_ptr;

cout<< Body adressen = <<身体<< endl;

ref_count = new int(1);

}


~Handle()//析构函数

{

(* ref_count) - ;

if(!* ref_count)

deleteAll();

}


T operator *()const {return * body; }


T&运营商*()

{

if(* ref_count> 1)

{

(* ref_count) - ;

body = new T(* body);

ref_count = new int(1);

}

返回* body;

}


T * operator->()

{

if(* ref_count> 1)

{

(* ref_count) - ;

body = new T(* body );

ref_count = new int(1);

}

返回正文;

}


T * operator->()const {return body; }

bool operator ==(const T& h){return * body == h; }

bool operator ==(const Handle& h){return * body == * h.body; }


句柄(const句柄& h)

{

body = h.body;

ref_count = h.ref_count;

(* ref_count)++;

}


int getRefCount(){return * ref_count; }

void operator()(Handle& h){cout<< * h.body<< ENDL; }


const Handle& operator =(const Handle& h)

{

if(this!=& h)

{

(* ref_count) - ;

if(!* ref_count)

deleteAll();

ref_count = h.ref_count;

body = h.body;

(* h.ref_count)++;

}

return * this;

}


私人:

T * body;

int * ref_count;


void deleteAll()

{

删除正文;

body = NULL;

删除ref_count;

ref_count = NULL;

}

};


无效addNodeToSTL(list< handle_t> * myList)

{

handle_t myh(new Integer(getValue(" Ange vardet som du vill lagga in i
$ b) $ b listan / listorna:")));

myList-> push_front(myh);

}

typedef Handle< Integer> ; handle_t;


int main()

{

list< handle_t> * myList1 = new list< handle_t> ;;

list< handle_t> * myList2 = new list< handle_t> ;;

do

{

switch(huvudMeny() )


{

案例0:返回0;

案例1:addNodeToSTL(myList1);

break;

case 2:displaySTL(myList1,myList2);

break;

case 3:deleteSelectedValue(myList1);

休息;

案例4:deleteAll(myList1);

休息;

案例5:findSelectedValue(myList1);

休息;

案例6:testOperatorStar(myList1);

休息;

案例7:testOperatorArrow(myList1 );

休息;

案例8:copyList(myList1,myList2);

休息;

}

} while(1);

返回0;

}


//非常感谢


// Tony

解决方案

Tony Johansson写道:

你好专家!!

这个课程模板和主要作品完美无缺。


我们将看到这一点。

我有这个名为Handle的类模板,其指针声明为
T * body;
正如你所看到的,我在课堂模板中有一个参考计数器,所以我知道
我对身体有多少参考。


好​​的。所以我的想法是执行


删除正文


当引用计数降到0.

在我的case它是整数
包装类,它是正文。
这个模板适用于许多不同的类型。
我使用的那个名为Integer,是int的包装器。这个代码
不包括
因为它没有添加任何进一步的信息。
在底部我有一个主要。
主要我可以单独调用支架函数addNodeToSTL以及更多
将节点添加到名为myList1的STL列表容器中。
这是将节点添加到STL列表容器的独立函数。
void addNodeToSTL(list< handle_t> ; * myList)
{
handle_t myh(new Integer(getValue(" Ange vardet som du vill lagga in i
listan / listorna:")));
myList - > push_front(myh);
}
这个handle_t是typedef到
typedef Handle< Integer> handle_t;

现在我的问题是当我向STL容器添加节点时,在我的情况下实际上是一个
引用对象。

STL内部是否有内容或者是我的班级模板
句柄。?


这实际上取决于实现,也可能取决于您使用的是哪个
容器:我将实现std :: vector< X>以这种方式

它只存储X类型的对象,但是std :: map< X>将是一棵树

结构和节点,为其分配存储可能看起来像这样:
这样:


模板< ; typename X>

class map_node {


X数据;

map_node * right;

map_node * left;

map_node * parent;


....


}; // clas map_node< X>

在任何情况下,您的代码都不应该依赖于有关标准容器内部

工作的任何假设,也不应该依赖于迭代器和算法。


现在供你参考计数指针:

模板< class T>
课程句柄
{
公开:
句柄()
{
body = new T(0);
ref_count = new int(1);
}


a)为什么T可以从0构造?

b)为什么不初始化:


句柄()

:body(新T())

,ref_count(new int(1))

{}


c)仍然,只是挑剔:如果新的int(1)失败,身体会泄漏内存。


所以,也许我们回到初始化:


句柄( ){

std :: auto_ptr< T> b_tmp = new T();

ref_count = new int(1);

body = b_tmp.release();

}

句柄(T * body_ptr)//构造函数
{
body = body_ptr;
cout<< Body adressen = <<身体<< endl;
ref_count = new int(1);
}


这里有一个类似的问题,虽然有人可能会说在这种情况下

调用者可以通过捕获异常来处理它。

〜句柄()//析构函数
{
(* ref_count) - ;
如果(!* ref_count)


制作


if(* ref_count == 0)


毕竟这是你想要与读者沟通的内容:

引用的数量是0.

deleteAll();
}

T operator *()const {return * body; }


您可能会考虑


T const& operator *()const {return * body; T& T& operator *()
{
if(* ref_count> 1)
{
(* ref_count) - ;


- (* ref_count)

; body = new T(* body);
ref_count = new int(1);


泄漏(见上文)

}
返回*正文;
}


这似乎实现了一个有趣的懒惰复制语义。


T * operator->()
{
if(* ref_count> 1)
{
(* ref_count) - ;
body = new T(* body);
ref_count = new int(1);
}
返回正文;
}


与T&
相同的评论
T * operator->()const {return body; }


可能你的意思是:


T const * operator->()const {return body; }


bool operator ==(const T& h){return * body == h; }
bool operator ==(const Handle& h){return * body == * h.body; }


您可以考虑转发<以及你可以为这些句柄使用std :: sort和

std :: set。

句柄(const句柄& h)
{
body = h.body;
ref_count = h.ref_count;
(* ref_count)++;
}


看起来很酷。

int getRefCount(){return * ref_count; }
void operator()(Handle& h){cout<< * h.body<< ENDL; }

const Handle& operator =(const Handle& h)
{
if(this!=& h)
{
(* ref_count) - ;
if(!* ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(* h.ref_count)++;
}
返回*这个;
}


嗯,怎么样


Hande& operator =(Handle const& other){

Handle dummy(other);

swap(* this,dummy);

return( *这个);

}


并且有一些朋友功能


swap(Handle& a,Handle & b){

swap(a.body,b.body);

swap(a.ref_count,b.ref_count);

}


注意这个赋值运算符如何将所有棘手的东西委托给副本

构造函数和析构函数:当dummy是

销毁。因此,您只需要正确地获得复制构造函数和析构函数。

特别是,如果复制构造函数是异常安全的,那么

赋值运算符也是如此。

私人:
T * body;
int * ref_count;

void deleteAll()
{
删除正文;
body = NULL;
删除ref_count;
ref_count = NULL;
}
};

void addNodeToSTL(list< handle_t> * myList)
{
handle_t myh(new Integer(getValue(" Ange vardet som du vill lagga in i
listan / listorna:")));
myList-> push_front(myh );
}
typedef Handle< Integer> handle_t;

int main()
{
list< handle_t> * myList1 = new list< handle_t> ;;
list< handle_t> * myList2 = new list< handle_t> ;;
切换(huvudMeny())

{0>案例0:返回0;
案例1:addNodeToSTL (myList1);
break;
案例2:displaySTL(myList1,myList2);
break;
案例3:deleteSelectedValue(myList1);
break;
案例4:deleteAll(myList1);
break;
案例5:findSelectedValue(myList1);
break;
案例6:testOperatorStar(myList1);
破解;
案例7:testOperatorArrow(myList1);
破解;
案例8:copyList(myList1,myList2);
break;
}
} while(1);
返回0;
}

//非常感谢

// Tony




您好//

感谢您提供有关代码的许多好建议,但我还有一个问题。


此代码用于assignement运算符和cpy-ctor。我的订单是错的

我必须有声明

ref_count = h.ref_count;之后

(* h.ref_count)++;

现在就是'以前'这是'错误的订单。

它'赋值运算符和cpy-ctor中的顺序错误相同。请你同意我的b $ b。?

句柄(const句柄& h)

{

body = h .body;

ref_count = h.ref_count;

(* ref_count)++;

}


const Handle& operator =(const Handle& h)

{

if(this!=& h)

{

(* ref_count) - ;

if(!* ref_count)

deleteAll();

ref_count = h.ref_count;

body = h.body;

(* h.ref_count)++;

}

return * this;

}


// Tony


我忘了提一件事:


Kai-Uwe Bux写道:

T& operator *()
{
if(* ref_count> 1)
{
(* ref_count) - ;
body = new T(* body);
ref_count = new int(1);
}
return * body;
}



这似乎实现了一个有趣的部分懒惰的复制语义。




请注意,这个复制语义意味着你的句柄不适合持有

指针,其类型的变化多态。行:


body = new T(* body);


将快速切片从T派生的任何对象。
< br $> b $ b最佳


Kai-Uwe Bux


Hello Experts!!

This class template and main works perfectly fine.
I have this class template called Handle that has a pointer declared as T*
body;
As you can see I have a reference counter in the class template so I know
how many references I have to the body. In my case it''s the Integer wrapper
class which is the body.
This template works for many different types.
The one that I use is named Integer and is a Wrapper for an int. The code
for this is not include
because it doesn''t add any futher information.
At the bottom I have a main.
In main I can call the stand alone function addNodeToSTL plus many more to
add nodes to the STL list container named myList1.
Here is the stand-alone function that add nodes to the STL list container.
void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}

This handle_t is typedef to
typedef Handle<Integer> handle_t;
Now to my question when I add nodes to a STL container what is actually a
referenceobject in my case.

Is it something that STL has internally or is it my class template Handle.?

template<class T>
class Handle
{
public:
Handle()
{
body = new T(0);
ref_count = new int(1);
}

Handle(T* body_ptr) //Constructor
{
body = body_ptr;
cout << "Body adressen = " << body << endl;
ref_count = new int(1);
}

~Handle() //Destructor
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
}

T operator*() const { return *body; }

T& operator*()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return *body;
}

T* operator->()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return body;
}

T* operator->() const { return body; }
bool operator==(const T& h) { return *body == h; }
bool operator==(const Handle& h) { return *body == *h.body; }

Handle(const Handle& h)
{
body = h.body;
ref_count = h.ref_count;
(*ref_count)++;
}

int getRefCount() { return *ref_count; }
void operator()(Handle& h) { cout << *h.body << endl; }

const Handle& operator=(const Handle& h)
{
if (this != &h)
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(*h.ref_count)++;
}
return *this;
}

private:
T* body;
int* ref_count;

void deleteAll()
{
delete body;
body = NULL;
delete ref_count;
ref_count = NULL;
}
};

void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}
typedef Handle<Integer> handle_t;

int main()
{
list<handle_t>* myList1 = new list<handle_t>;
list<handle_t>* myList2 = new list<handle_t>;
do
{
switch (huvudMeny())

{
case 0: return 0;
case 1: addNodeToSTL(myList1);
break;
case 2: displaySTL(myList1, myList2);
break;
case 3: deleteSelectedValue(myList1);
break;
case 4: deleteAll(myList1);
break;
case 5: findSelectedValue(myList1);
break;
case 6: testOperatorStar(myList1);
break;
case 7: testOperatorArrow(myList1);
break;
case 8: copyList(myList1, myList2);
break;
}
} while(1);
return 0;
}

//Many thanks

//Tony

解决方案

Tony Johansson wrote:

Hello Experts!!

This class template and main works perfectly fine.
We shall see about that.
I have this class template called Handle that has a pointer declared as
T* body;
As you can see I have a reference counter in the class template so I know
how many references I have to the body.
Ok. So the idea is to execute

delete body

when the reference count drops to 0.
In my case it''s the Integer
wrapper class which is the body.
This template works for many different types.
The one that I use is named Integer and is a Wrapper for an int. The code
for this is not include
because it doesn''t add any futher information.
At the bottom I have a main.
In main I can call the stand alone function addNodeToSTL plus many more
to add nodes to the STL list container named myList1.
Here is the stand-alone function that add nodes to the STL list container.
void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}

This handle_t is typedef to
typedef Handle<Integer> handle_t;
Now to my question when I add nodes to a STL container what is actually a
referenceobject in my case.

Is it something that STL has internally or is it my class template
Handle.?
That, actually is up to the implementation and also might depend on which
container you are using: I would implement std::vector<X> in such a way
that it just stores objects of type X, however std::map<X> would be a tree
structure and the nodes, for which storage would be allocated might look
like this:

template < typename X >
class map_node {

X data;
map_node * right;
map_node * left;
map_node * parent;

....

}; // clas map_node<X>

In any case, your code should not rely on any assumptions about the internal
workings of standard containers nor iterators nor algorithms.

Now for your reference counted pointer:

template<class T>
class Handle
{
public:
Handle()
{
body = new T(0);
ref_count = new int(1);
}
a) Why is T constructible from 0?
b) Why not initialize:

Handle ()
: body ( new T () )
, ref_count ( new int (1) )
{}

c) Still, just being picky: if new int(1) fails, body will leak memory.

So, maybe we are back to not initializing:

Handle () {
std::auto_ptr<T> b_tmp = new T();
ref_count = new int (1);
body = b_tmp.release();
}

Handle(T* body_ptr) //Constructor
{
body = body_ptr;
cout << "Body adressen = " << body << endl;
ref_count = new int(1);
}
There is a similar problem here, although one could argue that in this case
the caller could handle it by catching an exception.

~Handle() //Destructor
{
(*ref_count)--;
if (!*ref_count)
Make that

if ( *ref_count == 0 )

after all that is what you want to communicate to the reader: the number of
references is 0.
deleteAll();
}

T operator*() const { return *body; }
You might consider

T const & operator*() const { return *body; }

T& operator*()
{
if (*ref_count > 1)
{
(*ref_count)--;
-- (*ref_count)
; body = new T(*body);
ref_count = new int(1);
leak (see above)
}
return *body;
}
This seems to implement an interesting piece of lazy copy semantics.


T* operator->()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return body;
}
Same comments as for T&

T* operator->() const { return body; }
Probably you meant:

T const * operator->() const { return body; }

bool operator==(const T& h) { return *body == h; }
bool operator==(const Handle& h) { return *body == *h.body; }
You might consider forwarding < as well so that you could use std::sort and
std::set for these handles.
Handle(const Handle& h)
{
body = h.body;
ref_count = h.ref_count;
(*ref_count)++;
}
Looks cool.
int getRefCount() { return *ref_count; }
void operator()(Handle& h) { cout << *h.body << endl; }

const Handle& operator=(const Handle& h)
{
if (this != &h)
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(*h.ref_count)++;
}
return *this;
}
Hm, what about:

Hande & operator= ( Handle const & other ) {
Handle dummy ( other );
swap( *this, dummy );
return( *this );
}

and have some friend function

swap ( Handle & a, Handle & b ) {
swap( a.body, b.body );
swap( a.ref_count, b.ref_count );
}

Note how this assignment operator delegates all the tricky stuff to the copy
constructor and the destructor: the ref_counting is done when dummy is
destroyed. Thus you only have to get copy constructor and destructor right.
In particular, if the copy constructor is exception safe, then so is the
assignment operator.
private:
T* body;
int* ref_count;

void deleteAll()
{
delete body;
body = NULL;
delete ref_count;
ref_count = NULL;
}
};

void addNodeToSTL(list<handle_t>* myList)
{
handle_t myh(new Integer(getValue("Ange vardet som du vill lagga in i
listan/listorna: ")));
myList->push_front(myh);
}
typedef Handle<Integer> handle_t;

int main()
{
list<handle_t>* myList1 = new list<handle_t>;
list<handle_t>* myList2 = new list<handle_t>;
do
{
switch (huvudMeny())

{
case 0: return 0;
case 1: addNodeToSTL(myList1);
break;
case 2: displaySTL(myList1, myList2);
break;
case 3: deleteSelectedValue(myList1);
break;
case 4: deleteAll(myList1);
break;
case 5: findSelectedValue(myList1);
break;
case 6: testOperatorStar(myList1);
break;
case 7: testOperatorArrow(myList1);
break;
case 8: copyList(myList1, myList2);
break;
}
} while(1);
return 0;
}

//Many thanks

//Tony




Hello//
Thanks for many good suggestions about the code but I one more question.

This code for assignement operator and cpy-ctor. I thing the order is wrong
I must have statement
ref_count = h.ref_count; after
(*h.ref_count)++;
Now it''s before so that''s wrong order.
It''s the same order mistake in both assignment operator and the cpy-ctor. Do
you agree with me.?
Handle(const Handle& h)
{
body = h.body;
ref_count = h.ref_count;
(*ref_count)++;
}

const Handle& operator=(const Handle& h)
{
if (this != &h)
{
(*ref_count)--;
if (!*ref_count)
deleteAll();
ref_count = h.ref_count;
body = h.body;
(*h.ref_count)++;
}
return *this;
}

//Tony


I forgot to mention one thing:

Kai-Uwe Bux wrote:

T& operator*()
{
if (*ref_count > 1)
{
(*ref_count)--;
body = new T(*body);
ref_count = new int(1);
}
return *body;
}



This seems to implement an interesting piece of lazy copy semantics.



Note that this copy semantics implies that your handle is unfit for holding
pointers whose type varies polymorphically. The line:

body = new T(*body);

will cheerfully slice any object derived from T.

Best

Kai-Uwe Bux


这篇关于使用STL时的引用对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆