C++ 引用对象的 STL 容器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7707842/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
STL containers with reference to objects
提问by Vendetta
I know STL containers copy the objects. So say I have a
我知道 STL 容器复制对象。所以说我有一个
list<SampleClass> l;
each time when I do
每次当我做
SampleClass t(...);
l.push_back(t);
a copy of t will be made. If SampleClass is large, then it will be very costly.
将制作一份 t 副本。如果 SampleClass 很大,那么它会非常昂贵。
But if I declare l as a container of references,
但是如果我将 l 声明为引用的容器,
list<SampleClass&> l;
When I do
当我做
l.push_back(t);
Will it avoid copying the objects?
它会避免复制对象吗?
采纳答案by Dave Branton
Sadly no, it won't compile (with stlport at least). But the alternative, which is to store pointers to your objects in the container, will compile perfectly fine.
遗憾的是,它不会编译(至少使用 stlport)。但是另一种方法是将指向您的对象的指针存储在容器中,它将完美地编译。
This will leave you with a bit of extra syntactic noise around your code - you'll have to new things in order to insert them into your container.
这会给你的代码带来一些额外的语法干扰——你必须要有新的东西才能将它们插入到你的容器中。
std::list<class_type*> l;
l.push_back(new class_type);
However though the objects now won't be copied, they also won't be automatically cleaned up for you when the list is destructed. Smart pointers will solve this for you, but at the cost of even more syntactic noise. And since you can't put std::auto_ptr's in standard containers because they can't be copied, you have to use their slightly heavier-weight boost cousins, shared pointers.
但是,尽管现在不会复制对象,但当列表被破坏时,它们也不会自动为您清理。智能指针将为您解决这个问题,但代价是更多的句法噪音。并且由于不能将 std::auto_ptr 放入标准容器中,因为它们无法复制,因此您必须使用它们的重量稍重的 boost 表兄弟,共享指针。
std::list<boost::shared_ptr<class_type> > l;
l.push_back(boost::shared_ptr<class_type>(new class_type));
Shared pointed do incur some extra overhead, but it is minimal.
共享点确实会产生一些额外的开销,但它是最小的。
回答by Kerrek SB
If you know what you're doing, you can make a vector of references using std::reference_wrapper
:
如果您知道自己在做什么,则可以使用std::reference_wrapper
以下方法制作引用向量:
#include <functional>
#include <vector>
int main()
{
std::vector<std::reference_wrapper<int>> iv;
int a = 12;
iv.push_back(a); // or std::ref(a)
// now iv = { 12 };
a = 13;
// now iv = { 13 };
}
Note of course that any of this will come crashing down on you if any of the referred-to variables go out of scope while you're still holding references to them.
当然请注意,如果任何被引用的变量超出范围而您仍然持有对它们的引用,那么任何这些都会使您崩溃。
回答by Dennis Zickefoose
Standard library containers require their types be copiable; as references are not, you can't store them in containers to begin with. You can store pointers, so long as you are careful about object lifetimes. Boost has some pointer containers to help with that, or else you have smart pointers. Note, however, that auto_ptr
is notcopiable (as the standard defines it for this purpose), so shared_ptr
and unique_ptr
are your best bets now. Both are standard in C++11, and the former is supported through boost in C++03.
标准库容器要求它们的类型是可复制的;由于引用不是,因此您无法将它们存储在容器中。您可以存储指针,只要您注意对象的生命周期。Boost 有一些指针容器来帮助解决这个问题,或者你有智能指针。但是请注意,这auto_ptr
是不是可复制的(如该标准定义了它的了),所以shared_ptr
和unique_ptr
是你最好的赌注了。两者都是 C++11 中的标准,前者通过 C++03 中的 boost 支持。
回答by Mikhail
You want a container of pointers:
你想要一个指针容器:
list<SampleClass*> l;
回答by saha
Now that you have smart pointer, you can use it do the memory management and take raw pointers from them to use in STL containers. In that way you keep the ownership out of the container.
现在您有了智能指针,您可以使用它进行内存管理并从中获取原始指针以在 STL 容器中使用。通过这种方式,您可以将所有权排除在容器之外。
Here I have a unique_ptr of a tree, but used STL stack to store the raw pointers
这里我有一个树的 unique_ptr,但使用 STL 堆栈来存储原始指针
void TreeTraversal(unique_ptr<BinaryTreeNode>& root) {
stack<BinaryTreeNode *> _stack;
BinaryTreeNode *p = root.get();
_stack.push(p);
while(!_stack.empty()) {
p = _stack.top();
_stack.pop();
...
_stack.push(p->left);
_stack.push(p->right);
}
}
int main() {
unique_ptr<BinaryTreeNode> root = unique_ptr<BinaryTreeNode>(new BinaryTreeNode(...));
TreeTraversal(root);
}