Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在简单容器中存储对象引用_C++_Pointers_Stl_Reference_Containers - Fatal编程技术网

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();
}