0

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

11
  • 2
    The & isn't needed. Commented Sep 10, 2019 at 3:22
  • 1
    Could you explain in words what you are trying to do? Trying to guess how non-working code is supposed to work is not reliable. Commented Sep 10, 2019 at 3:23
  • 1
    Also, why do you need unique_ptr<vector<Node>> nodes;? Won't vector<Node> nodes; be enough? Commented Sep 10, 2019 at 3:25
  • The cur_node should always point to either none element or one of the nodes stored in nodes, but never to any other node? Commented Sep 10, 2019 at 6:42
  • The reason I ask is, that if that is the case then these two members should protected and the access/manipulation should be controlled by member function, otherwise this cannot be ensured. And if the access/manipulation is controlled by member function then you could use Node * for cur_node you anyhow need to do something like that because references or pointers to the elements in nodes can/will become invalid when you add new elements to that vector. Commented Sep 10, 2019 at 8:58

3 Answers 3

1

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;; } 
Sign up to request clarification or add additional context in comments.

6 Comments

Node has lots of fields, I want to be able to do cur_node.x = x; cur_node.val = y etc, otherwise I'd have to implement dozens of methods for that. I just read somewhere that a reference to a vector element can be unsafe, so I might just use indexing.
@Alex You can do cur_node().x = x; cur_node().val = y; just fine
Thanks @Caleth, that's exactly what I need
d.nodes->at(0).get(); would not work. It is unique_ptr<vector<Node>> nodes; and not unique_ptr<vector<unique_ptr<Node>>> nodes; So d.nodes->at(0) returns a reference to a Node. It would have to be &d.nodes->at(0).
Also I wonder if it's going to affect performance calling the function for setting every field
|
0

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; 

1 Comment

Thanks, like I said in the OP, I tried this, and I no longer could modify the original vector by modifying cur_node.
0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.