C++ 在简单容器中存储对象引用
我正在寻找一种方法,在一个容器对象中插入多个C++ 在简单容器中存储对象引用,c++,pointers,stl,reference,containers,C++,Pointers,Stl,Reference,Containers,我正在寻找一种方法,在一个容器对象中插入多个a类型的对象,而无需在插入过程中复制每个a对象。一种方法是通过引用容器来传递A对象,但不幸的是,据我所知,STL容器只接受通过值传递对象以进行插入(出于许多好的原因)。通常情况下,这不会是一个问题,但在我的情况下,我不希望调用复制构造函数并破坏原始对象,因为a是C库的包装器,其中包含一些指向结构的C样式指针,这些指针将与原始对象一起删除 我只需要一个容器,它可以返回它的一个对象,给定一个特定的索引,并存储在运行时确定的一定数量的项,所以我想也许我可以编
a
类型的对象,而无需在插入过程中复制每个a
对象。一种方法是通过引用容器来传递A
对象,但不幸的是,据我所知,STL容器只接受通过值传递对象以进行插入(出于许多好的原因)。通常情况下,这不会是一个问题,但在我的情况下,我不希望调用复制构造函数并破坏原始对象,因为a
是C库的包装器,其中包含一些指向结构的C样式指针,这些指针将与原始对象一起删除
我只需要一个容器,它可以返回它的一个对象,给定一个特定的索引,并存储在运行时确定的一定数量的项,所以我想也许我可以编写自己的容器类,但我不知道如何正确地做到这一点
另一种方法是将指向A
的指针存储在容器中,但由于我对这方面的知识不多,在STL容器中插入指向对象的指针的正确方法是什么?例如:
std::vector<A *> myVector;
for (unsigned int i = 0; i < n; ++i)
{
A *myObj = new myObj();
myVector.pushBack(myObj);
}
std::vector myVector;
for(无符号整数i=0;i
可能有用,但我不知道如何正确处理,如何以干净的方式处理。我应该仅仅依靠包含myVector的类的析构函数作为成员来处理它吗?如果此析构函数在删除其中一个包含的对象时引发异常,会发生什么情况
此外,有些人建议使用诸如
共享ptr
或自动ptr
或唯一ptr
之类的东西,但我对这么多选项感到困惑。对于我的场景,哪一个是最佳选择?您可以使用boost
或std
参考包装器
#include <boost/ref.hpp>
#include <vector>
struct A {};
int main()
{
A a, b, c, d;
std::vector< boost::reference_wrapper<A> > v;
v.push_back(boost::ref(a)); v.push_back(boost::ref(b));
v.push_back(boost::ref(c)); v.push_back(boost::ref(d));
return 0;
}
如果你需要处理这种情况,你需要一个智能指针
智能指针也是一种选择,但关键是要知道使用哪一种。如果您的数据实际上是共享的,请使用shared\u ptr
如果容器拥有该数据,请使用unique\u ptr
无论如何,我看不出A
的包装器部分会发生什么变化。如果它在内部包含指针并遵守命令,则不会出错。毁灭者将负责清理。这是C++中处理资源的典型方式:在对象初始化时获取资源,在对象生命周期结束时删除资源
如果纯粹想避免构建和删除的开销,您可能希望在C++11中使用vector::emplace_back
,您可以使用emplace
函数就地构建容器元素,从而避免管理指向已分配对象的指针容器的成本和麻烦:
std::vector<A> myVector;
for (unsigned int i = 0; i < n; ++i)
{
myVector.emplace_back();
}
std::vector myVector;
for(无符号整数i=0;i
如果对象的构造函数接受参数,则将它们传递给emplace
函数,该函数将转发它们
但是,如果对象是可复制或可移动的,则只能将其存储在向量中,因为在重新分配向量的存储时必须移动对象。您可以考虑让对象移动,转移托管资源的所有权,或者使用一个容器,比如“代码> DEQue<代码>或<代码>列表>代码>,它不会随着对象的增长而移动对象。
更新:由于这在编译器上不起作用,最好的选择可能是std::unique\u ptr
——它与普通指针相比没有开销,在从向量中删除对象时会自动删除,并允许您根据需要将所有权移出向量
如果不可用,则std::shared_ptr
(或std::tr1::shared_ptr
或boost::shared_ptr
,如果不可用)也会自动删除,但效率方面的成本(可能很小)
无论您做什么,都不要尝试将std::auto_ptr
存储在标准容器中。它的破坏性复制行为使您很容易在不希望的情况下意外删除对象
如果这些都不可用,则使用示例中的指针,并且确保在完成对象后记得删除它们。绝对不要使用auto\u ptr
或者boost::scoped\u ptr
或者std::unique\u ptr
都可以-std::vector
看看vector
或者boost::flyweight
@Keynslug>为什么flyweight
?我没有看到任何重复的数据。@pmr我没有看到。但是取决于这个容器的使用环境,flyweight
可能会解决整个问题。这真是太好了,Mike,但不幸的是,我使用的是VS 2010,它目前只提供了一个冗余的位置,如这里所述,所以我似乎无法使用这个功能,因为对象的构造函数接受一些参数:(@MihaiTodor:那太遗憾了。我已经用一些替代方法更新了答案。好的,很好!但是如果我使用std::unique\u ptr
或std::shared\u ptr
,内存是否会自动释放?我将如何处理向量?@mihaitor:是的,它们都会在销毁托管对象时删除(在共享\u ptr
的情况下,当指针的最后一个副本被销毁时)。在您的示例中,向量具有自动存储功能,因此当它超出范围时将自动销毁。这真的很好。在这种情况下,我肯定可以使用std::unique\u ptr
,但是,出于好奇,我想将此方法与使用std::reference\u wrapper
进行比较。我不确定哪种方法更好,请注意d在@pmr的a中
std::vector<A> myVector;
for (unsigned int i = 0; i < n; ++i)
{
myVector.emplace_back();
}