如何管理std :: list元素作为引用?

jsc*_*man 12 c++ reference

我有以下代码:

struct Foo {
    int var1;
    int var2;


    friend std::ostream& operator<<(std::ostream& os, const Foo& s){
        return os << "[Foo] " << s.var1 << "," <<  s.var2 ;
    }
};

int main() {
    Foo foo;
    foo.var1 = 1;
    foo.var2 = 2;
    std::list<Foo> list;
    list.push_back(foo);

    Foo &foo2 = list.front();
    foo2.var2 = 5;

    std::cout << "foo (" << &foo << "): " << foo << std::endl;
    std::cout << "foo2 (foo from list) (" << &list.front() << "): " << foo2 << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

我想要两个foofoo2引用同一个对象.因此,当我分配5foo2.var2,我也想修改foo.var2.然而,正如我们在以下输出中看到的那样,这种情况并没有发生:

foo (0x7fffffffe140): [Foo] 1,2
foo2 (foo from list) (0x61ac30): [Foo] 1,5 
Run Code Online (Sandbox Code Playgroud)

这样做的正确方法是什么?

vso*_*tco 17

当您使用push_back将元素插入列表时,push_back创建一个插入列表的副本.一种解决方案是使用std::reference_wrapper替代作为列表的基础类型,例如

std::list<std::reference_wrapper<Foo>> lst;
Run Code Online (Sandbox Code Playgroud)

然后像它一样推进它

lst.push_back(foo);
Run Code Online (Sandbox Code Playgroud)

这是一个超级简单的例子,向您展示它是如何工作的:

#include <functional>
#include <iostream>
#include <list>

int main() 
{
    int i = 42;
    std::list<std::reference_wrapper<int>> lst;

    lst.push_back(i);           // we add a "reference" into the list
    lst.front().get() = 10;     // we update the list
    std::cout << i;             // the initial i was modified!
}
Run Code Online (Sandbox Code Playgroud)

Live on Coliru

你需要的是reference_wrapper因为你不能简单地创建一个引用列表,比如std::list<Foo&>.或者,您可以使用指针,但我发现reference_wrapper方法更透明.

在上面的简单示例中,请注意需要使用std::reference_wrapper::get()获取基础引用,因为它reference_wrapper位于赋值运算符的左侧,因此不会隐式转换为intvia [ std::reference_wrapper::operator T&.

以下是修改为使用reference_wrappers的完整工作代码:

http://coliru.stacked-crooked.com/a/fb1fd67996d6e5e9