处理所有权的最佳方式 [英] Best way to handle ownership

查看:56
本文介绍了处理所有权的最佳方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




我最近遇到了一个问题,我决定将对象存储在一个向量中。

(以前,我总是在向量中存储指针)。当然,当使用push_back将一个对象存储在一个向量中时,我自然地将这个对象用于
手中的对象被复制(实际上是两次)。这导致了一个问题,因为我的

对象包含一个句柄。到另一个对象,当被推送的对象超出范围并被销毁时,被引用的对象也被销毁,使得向量内的副本引用一个现在不存在

对象。改变我的向量来存储指针而不是对象解决了

那个问题。但我想知道这是不是最好的处理

问题的方法。


我看到了几个选项。


一个是创建副本我的对象的构造函数,它创建了一个新的

对象和一个新的子对象。但这有两个问题。一,它是
意味着我正在使用额外的资源和时间制作额外的子对象

我真的不需要。二,这意味着获得处理那是存储在我推入向量的对象中的
(我想从

返回正在执行push_back的函数),我必须通过提取来获取它

对象退出向量并查询它,这似乎是浪费。


另一个想法是让我的拷贝构造函数取得<来自传递对象的
句柄。这意味着复制构造函数必须改变传递给它的对象的内容(将句柄设置为NULL),

但是......我已经声明了参数作为const参考!我没有感觉

从const引用改变它是一个好主意(虽然我可以

是错的......只是每当我做一个复制构造函数,我总是把参数作为一个const引用。


最后,我可以在向量中存储指针(并编写代码到

迭代向量以在我完成列表时销毁对象。)

这就是我最终选择做的事情。但我一开始就避免使用它,因为我不需要多态性,所以不需要存储指针,除了解决这个所有权问题之外,还需要



上述哪种方法可能被认为是更好? (或者是否有
这种带容器的工作的另一种范例?也许使用一些

类型的引用计数指针而不是我的<中的裸句柄 br />
对象?)


谢谢,

霍华德


Hi,

I recently had a problem where I decided to store objects in a vector.
(Previously, I had always stored pointers in vectors). Well, naturally,
when storing an object in a vector, using push_back, the object I had in
hand was getting copied (twice, in fact). That led to a problem, in that my
object contained a "handle" to another object, and when the object being
pushed went out of scope and was destroyed, the referenced object was also
destroyed, making the copy inside the vector refer to a now non-existent
object. Changing my vector to store pointers instead of objects resolved
that problem. But I''m wondering if that''s the "best" way to handle the
problem.

I see a few options.

One was to create a copy constructor for my object, which created a new
object and a new sub-object as well. But that had two problems. One, it
meant I was using extra resources and time making that extra sub-object that
I didn''t really need. Two, it meant that to get the "handle" that was
stored in the object I pushed into the vector (which I wanted to return from
the function that was doing the push_back), I had to get it by extracting
the object back out of the vector and querying it, which seemed a waste.

Another idea was to make my copy-constructor take ownership of the
handle from the passed object. That meant that the copy constructor had to
change the contents of the object passed to it (to set the handle to NULL),
but... I had declared the parameter as a const reference! I didn''t feel
that changing that from a const reference was a great idea (although I could
be wrong...it''s just that whenever I make a copy constructor, I always make
the parameter a const reference).

And lastly, I could store pointers in the vector (and write code to
iterate of the vector to destroy the objects when I was done with the list).
That''s what I chose to do eventually. But I avoided it at first because I
have no need for polymorphism, so storing pointers wasn''t really needed,
except to resolve this ownership issue.

Which of the above methods might be considered "better"? (Or is there
another paradigm for this kind of work with containers? Perhaps using some
kind of reference-counted pointer instead of the bare "handle" inside my
object?)

Thanks,
Howard


推荐答案

" Howard" <人***** @ hotmail.com>在留言中写道

news:uL ******************* @ bgtnsc04-news.ops.worldnet.att.net ...
"Howard" <al*****@hotmail.com> wrote in message
news:uL*******************@bgtnsc04-news.ops.worldnet.att.net...
我最近遇到了一个问题,我决定将对象存储在向量中。
(以前,我总是在向量中存储指针)。嗯,当然,当使用push_back将对象存储在向量中时,我手中的对象被复制(实际上是两次)。这导致了一个问题,因为我的对象包含一个句柄。到另一个对象,当被推送的对象超出范围并被销毁时,引用的对象也被销毁,使得向量内的副本引用现在不存在的
宾语。


你没有遵守三条规则吗? :)你显然写了一个析构函数,

但没有定义复制构造函数或至少私下声明它。

更改我的向量来存储指针而不是对象解析了<问题。但我想知道这是不是最好的处理问题的方法。


如果因任何原因复制您的对象是不可行的,您应该禁止

复制。在这种情况下,你唯一的选择是使用指针,这会带来

他们的所有权问题,因此你的主题。


因此,最好的事情要做的就是将智能指针存储在

的向量中:


#include< boost / shared_ptr.hpp>


typedef boost :: shared_ptr< MyClass> MyClassPtr;


#include< vector>


typedef std :: vector< MyClassPtr> MyObjects;

我看到了一些选项。

一个是为我的对象创建一个复制构造函数,它创建了一个新的
对象和一个新的子对象同样。但这有两个问题。一,它意味着我正在使用额外的资源和时间来制作我真正不需要的额外子对象。二,这意味着获得处理
存储在我推入向量的对象中(我想从正在执行push_back的函数返回),我必须通过
提取对象来获取它向量并查询它,这似乎是一种浪费。

另一个想法是让我的复制构造函数从传递的对象中获取
句柄的所有权。


不是个好主意。这正是为什么std :: auto_ptr不能与标准容器一起使用的原因。

标准容器要求对象是可复制构造的并且

副本是等价的。

这意味着复制构造函数必须更改传递给它的
对象的内容(将句柄设置为NULL),但...


不要这样做:)

我已经将参数声明为const参考!我不觉得从const引用中改变它是一个好主意(虽然我可能是错误的......只是每当我制作一个复制构造函数时,我总是这样做
参数一个const引用)。


你能用一个引用计数指针(例如boost :: shared_ptr)作为

句柄吗?这将使你的对象的副本共享句柄

而不是拥有句柄。

最后,我可以在向量中存储指针(并且当我完成
列表时,将代码写入
迭代向量以销毁对象)。


显式调用delete会使您的代码异常 - 不安全。在向量中使用smart

指针。

这就是我最终选择做的事情。但我一开始就避免使用它,因为我不需要多态性,所以不需要存储指针,
除了解决这个所有权问题。


指针不仅适用于多态性。动态对象允许我们扩展

对象的生命周期:它们不是自动对象,这意味着它们不会自动被销毁。

哪个可以认为上述方法中的更好? (或者是否存在使用容器进行此类工作的另一种范例?也许使用某种引用计数指针而不是我的对象里面的裸句柄?)
I recently had a problem where I decided to store objects in a vector.
(Previously, I had always stored pointers in vectors). Well, naturally,
when storing an object in a vector, using push_back, the object I had in
hand was getting copied (twice, in fact). That led to a problem, in that
my object contained a "handle" to another object, and when the object
being pushed went out of scope and was destroyed, the referenced object
was also destroyed, making the copy inside the vector refer to a now
non-existent object.
Did you not observe the rule of three? :) You obviously wrote a destructor,
but did not define the copy constructor or at least declared it privately.
Changing my vector to store pointers instead of objects resolved that
problem. But I''m wondering if that''s the "best" way to handle the
problem.
If copying your objects is not viable for any reason, you should disallow
copying. In that case, your only option is to use pointers, which bring
their ownership problems, hence your subject line.

For that reason, the best thing to do would be to store smart pointers in
the vector:

#include <boost/shared_ptr.hpp>

typedef boost::shared_ptr<MyClass> MyClassPtr;

#include <vector>

typedef std::vector<MyClassPtr> MyObjects;
I see a few options.

One was to create a copy constructor for my object, which created a new
object and a new sub-object as well. But that had two problems. One, it
meant I was using extra resources and time making that extra sub-object
that I didn''t really need. Two, it meant that to get the "handle" that
was stored in the object I pushed into the vector (which I wanted to
return from the function that was doing the push_back), I had to get it by
extracting the object back out of the vector and querying it, which seemed
a waste.

Another idea was to make my copy-constructor take ownership of the
handle from the passed object.
Not a good idea. That is precisely the reason why std::auto_ptr cannot be
used with standard containers.

Standard containers require that the objects are copy constructible and that
the copies are equivalent.
That meant that the copy constructor had to change the contents of the
object passed to it (to set the handle to NULL), but...
Don''t do it :)
I had declared the parameter as a const reference! I didn''t feel that
changing that from a const reference was a great idea (although I could be
wrong...it''s just that whenever I make a copy constructor, I always make
the parameter a const reference).
Could you use a reference counted pointer (e.g. boost::shared_ptr) for the
handle? That would make the copies of your objects "share the handle"
instead of "own the handle."
And lastly, I could store pointers in the vector (and write code to
iterate of the vector to destroy the objects when I was done with the
list).
Calling delete explicitly makes your code exception-unsafe. Use smart
pointers in the vector.
That''s what I chose to do eventually. But I avoided it at first because I
have no need for polymorphism, so storing pointers wasn''t really needed,
except to resolve this ownership issue.
Pointers are not only for polymorphism. Dynamic objects allow us extend
object lifetimes: they are not automatic objects, meaning that they don''t
get destroyed automatically.
Which of the above methods might be considered "better"? (Or is there
another paradigm for this kind of work with containers? Perhaps using
some kind of reference-counted pointer instead of the bare "handle" inside
my object?)




这个,或者使用向量中的引用计数指针。


Ali

-

插头:ACCU的硅谷分会在第二个星期二开会。会议

免费向公众开放。今晚请来谈谈

Ada:

http://accu-usa.org/index.html



Either that, or use reference counted pointers in the vector.

Ali
--
Plug: ACCU''s Silicon Valley Chapter meets on second Tuesdays. The meetings
are open to public and free of charge. Please come tonight for a talk on
Ada:

http://accu-usa.org/index.html


Howard写道:


我最近遇到了一个问题,我决定将对象存储在向量中。
(以前,我总是在向量中存储指针)。嗯,当然,当使用push_back将对象存储在向量中时,我手中的对象被复制(实际上是两次)。这导致了一个问题,因为我的
对象包含一个句柄。到另一个对象,并且当被推送的对象超出范围并被销毁时,引用的对象也被销毁,使得向量内的副本引用现在不存在的
宾语。改变我的向量来存储指针而不是对象解决了那个问题。但我想知道这是不是最好的处理
问题的方法。

我看到了一些选项。

一个是为我的对象创建一个复制构造函数,它创建了一个新的
对象和新的子对象。但这有两个问题。一,它意味着我正在使用额外的资源和时间制作那些我真的不需要的额外子对象。二,这意味着获得处理那是存储在我推入向量的对象中的(我想从
函数返回push_back),我必须通过提取
对象来获取它向量并查询它,这似乎是一种浪费。

另一个想法是让我的复制构造函数从传递的对象中获取
句柄的所有权。这意味着复制构造函数必须更改传递给它的对象的内容(将句柄设置为NULL),但是......我已经将参数声明为const引用!我不觉得从const引用中改变它是一个好主意(尽管我可能会错误......只是每当我制作一个复制构造函数时,我总是这样做
参数一个const引用。

最后,我可以在向量中存储指针(并编写代码来迭代向量以在我完成时销毁对象)列表)。
这就是我最终选择做的事情。但我一开始就避免使用它,因为我不需要多态性,所以不需要存储指针,除了解决这个所有权问题之外。

哪个是以上方法可能会被认为是更好的? (或者是否存在使用容器进行此类工作的另一种范例?也许在我的
对象中使用一些引用计数指针而不是裸露的句柄?) />
谢谢,
霍华德
Hi,

I recently had a problem where I decided to store objects in a vector.
(Previously, I had always stored pointers in vectors). Well, naturally,
when storing an object in a vector, using push_back, the object I had in
hand was getting copied (twice, in fact). That led to a problem, in that my
object contained a "handle" to another object, and when the object being
pushed went out of scope and was destroyed, the referenced object was also
destroyed, making the copy inside the vector refer to a now non-existent
object. Changing my vector to store pointers instead of objects resolved
that problem. But I''m wondering if that''s the "best" way to handle the
problem.

I see a few options.

One was to create a copy constructor for my object, which created a new
object and a new sub-object as well. But that had two problems. One, it
meant I was using extra resources and time making that extra sub-object that
I didn''t really need. Two, it meant that to get the "handle" that was
stored in the object I pushed into the vector (which I wanted to return from
the function that was doing the push_back), I had to get it by extracting
the object back out of the vector and querying it, which seemed a waste.

Another idea was to make my copy-constructor take ownership of the
handle from the passed object. That meant that the copy constructor had to
change the contents of the object passed to it (to set the handle to NULL),
but... I had declared the parameter as a const reference! I didn''t feel
that changing that from a const reference was a great idea (although I could
be wrong...it''s just that whenever I make a copy constructor, I always make
the parameter a const reference).

And lastly, I could store pointers in the vector (and write code to
iterate of the vector to destroy the objects when I was done with the list).
That''s what I chose to do eventually. But I avoided it at first because I
have no need for polymorphism, so storing pointers wasn''t really needed,
except to resolve this ownership issue.

Which of the above methods might be considered "better"? (Or is there
another paradigm for this kind of work with containers? Perhaps using some
kind of reference-counted pointer instead of the bare "handle" inside my
object?)

Thanks,
Howard




你好霍华德,

你能提供样品吗?您选择使用的代码?

问候,

Peter Jansson



Hello Howard,
Could you please provide a sample of the code you selected to use?
Regards,
Peter Jansson




Peter Jansson <我们******* @ jansson.net>在消息中写道

news:21 ********************* @ newsc.telia.net ...

"Peter Jansson" <we*******@jansson.net> wrote in message
news:21*********************@newsc.telia.net...
霍华德写道:



你好霍华德,
你能否提供你选择使用的代码示例?
问候,
Peter Jansson



Hello Howard,
Could you please provide a sample of the code you selected to use?
Regards,
Peter Jansson




当然:


HFONT AFonts :: FontByNameAndSize(const char * name,short尺寸)

{

HFONT hFont = 0;

bool found = false;

//看看是否字体已经创建了

for(AFontIterator iter = fFonts.begin(); iter!= fFonts.end(); ++ iter)

{

AFont * pFont =(AFont *)&(* iter);

if((!strcmp(pFont-> fName,name))&&

(pFont-> fSize == size))

{

hFont = pFont-> fHFont;

found = true;

}

}

//如果没有,创建它

if(!found)

{

AFont * pFont = new AFont(名称,大小);

hFont = pFont-> fHFont;

fFonts.push_back(pFont);

}

返回hFont;

}


之前,最后一部分是这样的:


AFont tempFont(名称,大小);

hFont = tempFont.fHFont;

fFonts.push_back(tempFont);


(fHFont是句柄,一个Windows字体资源句柄,我在AFont对象的构造函数中创建了

。)


-Howard



Sure:

HFONT AFonts::FontByNameAndSize( const char* name, short size )
{
HFONT hFont = 0;
bool found = false;
// see if font already created
for (AFontIterator iter = fFonts.begin(); iter != fFonts.end(); ++iter )
{
AFont* pFont = (AFont*)&(*iter);
if ((!strcmp(pFont->fName,name)) &&
(pFont->fSize == size))
{
hFont = pFont->fHFont;
found = true;
}
}
// if not, create it
if (!found)
{
AFont* pFont = new AFont( name, size );
hFont = pFont->fHFont;
fFonts.push_back( pFont );
}
return hFont;
}

previously, that last part was like this:

AFont tempFont( name, size );
hFont = tempFont.fHFont;
fFonts.push_back( tempFont );

(The fHFont is the "handle", a Windows Font resource handle, which I create
in the constructor of an AFont object.)

-Howard


这篇关于处理所有权的最佳方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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