Alex
Alex

Reputation: 36171

How to use a unique_ptr reference to a vector element?

I just started learning C++.

In C I would just use Node* cur_node, but in C++ this doesn't work:


struct Node {
        int val;
};

struct Foo {
        unique_ptr<vector<Node>> nodes;
        unique_ptr<&Node> cur_node;
};


int main() {
        Foo foo;
        foo.nodes = make_unique<vector<Node>>();
        foo.nodes->push_back((Node){.val=100});
        //d.cur_node = d.nodes[0];
        foo.cur_node = make_unique<&Node>(((*d.nodes)[0]));
        (*d.nodes)[0].val = 200;
        cout << d.cur_node->val << endl;;
        cout << (*d.nodes)[0].val << endl;;
}


error: 'Node' does not refer to a value
        unique_ptr<&Node> cur_node;

If I don't use a reference, the value is copied, and I can't modify the original vector by modifying cur_node.

Maybe I need shared_ptr for this?

edit

To make it more clear: I want cur_node to contain a reference to one of the values in the vector, and to modify the original vector by modifying cur_node, just like I would with raw C pointers.

Thanks

Upvotes: 0

Views: 1273

Answers (3)

Caleth
Caleth

Reputation: 63297

You can still use Node *, however you need to be careful of the vector's pointer invalidation rules.

struct Foo {
    unique_ptr<vector<Node>> nodes;
    Node * cur_node;
};


int main() {
    Foo foo;
    foo.nodes = make_unique<vector<Node>>();
    foo.nodes->push_back((Node){.val=100});
    foo.cur_node = &d.nodes->at(0);
    d.nodes->at(0).val = 200;
    cout << d.cur_node->val << endl;;
    cout << d.nodes->at(0).val << endl;;
}

Why not just hold the index?

struct Foo {
    unique_ptr<vector<Node>> nodes;
    size_t cur_index; 
    Node & cur_node() { return nodes->at(cur_index); }
};


int main() {
    Foo foo;
    foo.nodes = make_unique<vector<Node>>();
    foo.nodes->push_back((Node){.val=100});
    foo.cur_index = 0;
    d.nodes->at(0).val = 200;
    cout << d.cur_node().val << endl;;
    cout << d.nodes->at(0).val << endl;;
}

Upvotes: 1

ObliteratedJillo
ObliteratedJillo

Reputation: 5166

Yes, use std::shared_ptr . Presuming Node is a large struct and don't want to store by value in Foo here's how you can do:

struct Foo {
    vector<std::shared_ptr<Node>> nodes;
    std::shared_ptr<Node> cur_node;
};

int main()
{
    vector<std::shared_ptr<Node>> vec = { make_shared<Node>(100 ), make_shared<Node>(200) };

    Foo foo;
    foo.nodes.push_back(vec[0]);

    cout << foo.nodes[0]->val << endl;
    cout << foo.cur_node->val << endl;
}

Upvotes: 0

user10957435
user10957435

Reputation:

unique_ptr is a template. It doesn't need an & in the type. In fact, I don't think an & makes sense in there in this context at all in C++. & usually means the address of a concrete variable, not a type.

Just do this instead:

uniqure_ptr<Node> cur_node;

Upvotes: 0

Related Questions