Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.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++ 参照对象的STL容器_C++_Stl_Reference_Pass By Reference - Fatal编程技术网

C++ 参照对象的STL容器

C++ 参照对象的STL容器,c++,stl,reference,pass-by-reference,C++,Stl,Reference,Pass By Reference,我知道STL容器复制对象。所以说我有一个 list<SampleClass> l; 将制作一份t。如果SampleClass很大,那么它将非常昂贵 但是如果我把l声明为引用的容器 list<SampleClass&> l; 它会避免复制对象吗?遗憾的是,它不会编译(至少使用stlport)。但另一种选择是将指向对象的指针存储在容器中,这样可以很好地编译 这将在代码周围留下一点额外的语法噪音——为了将它们插入到容器中,您必须使用新的东西 std::list<

我知道STL容器复制对象。所以说我有一个

list<SampleClass> l;
将制作一份t。如果SampleClass很大,那么它将非常昂贵

但是如果我把l声明为引用的容器

list<SampleClass&> l;

它会避免复制对象吗?

遗憾的是,它不会编译(至少使用stlport)。但另一种选择是将指向对象的指针存储在容器中,这样可以很好地编译

这将在代码周围留下一点额外的语法噪音——为了将它们插入到容器中,您必须使用新的东西

std::list<class_type*> l;
l.push_back(new class_type);
std::list l;
l、 推回(新的类别类型);
但是,虽然现在不会复制对象,但在销毁列表时也不会自动为您清理对象。智能指针将为您解决这个问题,但代价是更多的语法噪音。由于无法复制std::auto_ptr,所以无法将其放入标准容器中,因此必须使用稍重的重量提升表,即共享指针

std::list<boost::shared_ptr<class_type> > l;
l.push_back(boost::shared_ptr<class_type>(new class_type));
std::list l;
l、 push_back(boost::shared_ptr(新类类型));

共享点确实会产生一些额外的开销,但这是最小的。

标准库容器要求其类型是可复制的;由于引用不是,所以您不能首先将它们存储在容器中。您可以存储指针,只要您对对象生命周期非常小心。Boost有一些指针容器来帮助实现这一点,或者您有智能指针。但是,请注意,
auto\u ptr
是不可复制的(正如标准为此定义的那样),因此
shared\u ptr
unique\u ptr
现在是您的最佳选择。两者在C++11中都是标准的,前者通过C++03中的boost得到支持

如果您知道自己在做什么,可以使用
std::reference\u 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 };
}
#包括
#包括
int main()
{
std::载体iv;
INTA=12;
iv.向后推(a);//或标准::参考(a)
//现在iv={12};
a=13;
//现在iv={13};
}

当然,请注意,如果引用的任何变量在您仍保留对它们的引用时超出范围,则所有这些都将崩溃。

您需要一个指针容器:

list<SampleClass*> l;
列表l;

现在您有了智能指针,您可以使用它进行内存管理,并从中获取原始指针以在STL容器中使用。通过这种方式,您可以将所有权排除在容器之外

std::list<class_type*> l;
l.push_back(new class_type);
在这里,我有一个独特的树,但使用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);
}
void TreeTraversal(唯一的\u ptr&root){
堆栈(u堆栈),;
BinaryTreeNode*p=root.get();
_栈推(p);
而(!\u stack.empty()){
p=_stack.top();
_stack.pop();
...
_栈.推(p->左);
_栈.推(p->右);
}
}
int main(){
unique_ptr root=unique_ptr(新的二元三萜(…));
树根;
}

事实上,现在我想起来了。。。考虑到11中按函数分解需求的方式,如果您将自己限制在一个足够小的操作子集内,则可能存储一个引用类型,但子集将非常有限。正确:我认为
reference\u wrapper
s应该优先于原始指针,为了清楚地传达非所有权,请避免使用粗糙的指针语法(交换条件是中断
auto
并有时不得不使用
.get()
),并避免未初始化指针或
nullptr
或意外执行指针算术等。
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);
}