Returning shared pointer reference breaks outside of class methods
I have a tree in C++ and a method in the Tree that returns a shared_ptr reference to a new leaf whenever that leaf is added to the tree. When I use this inside other methods of the Tree class it works fine, but when I try to call it from main, it crashes, despite the code seemingly doing the same thing.
Here's the Node and Tree classes:
#include <iostream>
#include <vector>
#include <memory>
class Node
public:
int value;
std::vector<std::shared_ptr<Node> > children;
Node(int value): valuevalue
;
class Tree
public:
std::shared_ptr<Node> root;
Tree(): root nullptr
std::shared_ptr<Node> CreateLeaf(int value)
return std::make_shared<Node>(value);
std::shared_ptr<Node>& AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
void otherMethod()
AddLeaf(1, root);
std::shared_ptr<Node>& temporary = AddLeaf(2, root);
std::cout << "temporary->value: " << temporary->value << std::endl;
;
If the main function is:
int main()
Tree t;
t.otherMethod();
Then the program runs correctly.
However, if the main function is:
int main()
Tree t;
t.AddLeaf(1, t.root);
std::shared_ptr<Node>& b = t.AddLeaf(2, t.root);
std::cout << "b->value = " << b->value << std::endl;
the program crashes, despite it doing pretty much the same thing. It seems like AddLeaf is just storing the nullptr in b, despite it being a reference to a persistent object, t.root->children[0]. Why is it doing that?
c++ tree shared-ptr
add a comment |
I have a tree in C++ and a method in the Tree that returns a shared_ptr reference to a new leaf whenever that leaf is added to the tree. When I use this inside other methods of the Tree class it works fine, but when I try to call it from main, it crashes, despite the code seemingly doing the same thing.
Here's the Node and Tree classes:
#include <iostream>
#include <vector>
#include <memory>
class Node
public:
int value;
std::vector<std::shared_ptr<Node> > children;
Node(int value): valuevalue
;
class Tree
public:
std::shared_ptr<Node> root;
Tree(): root nullptr
std::shared_ptr<Node> CreateLeaf(int value)
return std::make_shared<Node>(value);
std::shared_ptr<Node>& AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
void otherMethod()
AddLeaf(1, root);
std::shared_ptr<Node>& temporary = AddLeaf(2, root);
std::cout << "temporary->value: " << temporary->value << std::endl;
;
If the main function is:
int main()
Tree t;
t.otherMethod();
Then the program runs correctly.
However, if the main function is:
int main()
Tree t;
t.AddLeaf(1, t.root);
std::shared_ptr<Node>& b = t.AddLeaf(2, t.root);
std::cout << "b->value = " << b->value << std::endl;
the program crashes, despite it doing pretty much the same thing. It seems like AddLeaf is just storing the nullptr in b, despite it being a reference to a persistent object, t.root->children[0]. Why is it doing that?
c++ tree shared-ptr
add a comment |
I have a tree in C++ and a method in the Tree that returns a shared_ptr reference to a new leaf whenever that leaf is added to the tree. When I use this inside other methods of the Tree class it works fine, but when I try to call it from main, it crashes, despite the code seemingly doing the same thing.
Here's the Node and Tree classes:
#include <iostream>
#include <vector>
#include <memory>
class Node
public:
int value;
std::vector<std::shared_ptr<Node> > children;
Node(int value): valuevalue
;
class Tree
public:
std::shared_ptr<Node> root;
Tree(): root nullptr
std::shared_ptr<Node> CreateLeaf(int value)
return std::make_shared<Node>(value);
std::shared_ptr<Node>& AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
void otherMethod()
AddLeaf(1, root);
std::shared_ptr<Node>& temporary = AddLeaf(2, root);
std::cout << "temporary->value: " << temporary->value << std::endl;
;
If the main function is:
int main()
Tree t;
t.otherMethod();
Then the program runs correctly.
However, if the main function is:
int main()
Tree t;
t.AddLeaf(1, t.root);
std::shared_ptr<Node>& b = t.AddLeaf(2, t.root);
std::cout << "b->value = " << b->value << std::endl;
the program crashes, despite it doing pretty much the same thing. It seems like AddLeaf is just storing the nullptr in b, despite it being a reference to a persistent object, t.root->children[0]. Why is it doing that?
c++ tree shared-ptr
I have a tree in C++ and a method in the Tree that returns a shared_ptr reference to a new leaf whenever that leaf is added to the tree. When I use this inside other methods of the Tree class it works fine, but when I try to call it from main, it crashes, despite the code seemingly doing the same thing.
Here's the Node and Tree classes:
#include <iostream>
#include <vector>
#include <memory>
class Node
public:
int value;
std::vector<std::shared_ptr<Node> > children;
Node(int value): valuevalue
;
class Tree
public:
std::shared_ptr<Node> root;
Tree(): root nullptr
std::shared_ptr<Node> CreateLeaf(int value)
return std::make_shared<Node>(value);
std::shared_ptr<Node>& AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
void otherMethod()
AddLeaf(1, root);
std::shared_ptr<Node>& temporary = AddLeaf(2, root);
std::cout << "temporary->value: " << temporary->value << std::endl;
;
If the main function is:
int main()
Tree t;
t.otherMethod();
Then the program runs correctly.
However, if the main function is:
int main()
Tree t;
t.AddLeaf(1, t.root);
std::shared_ptr<Node>& b = t.AddLeaf(2, t.root);
std::cout << "b->value = " << b->value << std::endl;
the program crashes, despite it doing pretty much the same thing. It seems like AddLeaf is just storing the nullptr in b, despite it being a reference to a persistent object, t.root->children[0]. Why is it doing that?
c++ tree shared-ptr
c++ tree shared-ptr
asked Nov 15 '18 at 13:21
user2520385user2520385
841616
841616
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Having references to elements in a vector, or any self-resizing container, is dangerous. I've dealt with this when I created my first game in C++.
Essentially what happens is:
Your vector resizes when adding a new shared_ptr, which may cause an operation to allocate more memory. During that procedure the currently existing vector is destructed and allocated on possibly a different location in memory.
Meaning that all currently existing pointers or references to elements in the vector become invalidated and may crash your program at some point.
Passing out references to shared_ptr's in a vector basically promotes undefined behavior. A smarter move would be to just return a new shared_ptr and have the reference counter just increment.
That way, when the vector resizes, no reference in your program gets invalidated.
Removing the reference should help:
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
Anyway, as I see you're creating a tree, perhaps you would like to take a look at code I've written in an (abandoned) project: https://github.com/wvanbreukelen/LexMe/blob/feature-tree-node-vector-specialization/LexMe/TreeNode.h
It's a quite complete implementation for a generic tree with friendliness towards move semantics and iterators.
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53320441%2freturning-shared-pointer-reference-breaks-outside-of-class-methods%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Having references to elements in a vector, or any self-resizing container, is dangerous. I've dealt with this when I created my first game in C++.
Essentially what happens is:
Your vector resizes when adding a new shared_ptr, which may cause an operation to allocate more memory. During that procedure the currently existing vector is destructed and allocated on possibly a different location in memory.
Meaning that all currently existing pointers or references to elements in the vector become invalidated and may crash your program at some point.
Passing out references to shared_ptr's in a vector basically promotes undefined behavior. A smarter move would be to just return a new shared_ptr and have the reference counter just increment.
That way, when the vector resizes, no reference in your program gets invalidated.
Removing the reference should help:
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
Anyway, as I see you're creating a tree, perhaps you would like to take a look at code I've written in an (abandoned) project: https://github.com/wvanbreukelen/LexMe/blob/feature-tree-node-vector-specialization/LexMe/TreeNode.h
It's a quite complete implementation for a generic tree with friendliness towards move semantics and iterators.
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
|
show 2 more comments
Having references to elements in a vector, or any self-resizing container, is dangerous. I've dealt with this when I created my first game in C++.
Essentially what happens is:
Your vector resizes when adding a new shared_ptr, which may cause an operation to allocate more memory. During that procedure the currently existing vector is destructed and allocated on possibly a different location in memory.
Meaning that all currently existing pointers or references to elements in the vector become invalidated and may crash your program at some point.
Passing out references to shared_ptr's in a vector basically promotes undefined behavior. A smarter move would be to just return a new shared_ptr and have the reference counter just increment.
That way, when the vector resizes, no reference in your program gets invalidated.
Removing the reference should help:
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
Anyway, as I see you're creating a tree, perhaps you would like to take a look at code I've written in an (abandoned) project: https://github.com/wvanbreukelen/LexMe/blob/feature-tree-node-vector-specialization/LexMe/TreeNode.h
It's a quite complete implementation for a generic tree with friendliness towards move semantics and iterators.
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
|
show 2 more comments
Having references to elements in a vector, or any self-resizing container, is dangerous. I've dealt with this when I created my first game in C++.
Essentially what happens is:
Your vector resizes when adding a new shared_ptr, which may cause an operation to allocate more memory. During that procedure the currently existing vector is destructed and allocated on possibly a different location in memory.
Meaning that all currently existing pointers or references to elements in the vector become invalidated and may crash your program at some point.
Passing out references to shared_ptr's in a vector basically promotes undefined behavior. A smarter move would be to just return a new shared_ptr and have the reference counter just increment.
That way, when the vector resizes, no reference in your program gets invalidated.
Removing the reference should help:
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
Anyway, as I see you're creating a tree, perhaps you would like to take a look at code I've written in an (abandoned) project: https://github.com/wvanbreukelen/LexMe/blob/feature-tree-node-vector-specialization/LexMe/TreeNode.h
It's a quite complete implementation for a generic tree with friendliness towards move semantics and iterators.
Having references to elements in a vector, or any self-resizing container, is dangerous. I've dealt with this when I created my first game in C++.
Essentially what happens is:
Your vector resizes when adding a new shared_ptr, which may cause an operation to allocate more memory. During that procedure the currently existing vector is destructed and allocated on possibly a different location in memory.
Meaning that all currently existing pointers or references to elements in the vector become invalidated and may crash your program at some point.
Passing out references to shared_ptr's in a vector basically promotes undefined behavior. A smarter move would be to just return a new shared_ptr and have the reference counter just increment.
That way, when the vector resizes, no reference in your program gets invalidated.
Removing the reference should help:
std::shared_ptr<Node> AddLeaf(int value, std::shared_ptr<Node>& ptr)
if(ptr == nullptr)
ptr = std::move(CreateLeaf(value));
return ptr;
else
std::shared_ptr<Node> newLeaf = CreateLeaf(value);
ptr->children.push_back(std::move(newLeaf));
return ptr->children.back();
Anyway, as I see you're creating a tree, perhaps you would like to take a look at code I've written in an (abandoned) project: https://github.com/wvanbreukelen/LexMe/blob/feature-tree-node-vector-specialization/LexMe/TreeNode.h
It's a quite complete implementation for a generic tree with friendliness towards move semantics and iterators.
edited Nov 15 '18 at 13:59
answered Nov 15 '18 at 13:49
Julian vDJulian vD
889
889
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
|
show 2 more comments
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
"Meaning that all currently existing pointers to elements in the vector become invalidated and may crash your program at some point." Where do you see existing pointers to vector elements in this code?
– melpomene
Nov 15 '18 at 13:59
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
In this case, it is actually a reference, but semantically it's the about same. I'll edit the answer
– Julian vD
Nov 15 '18 at 14:00
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
OK, where are the existing references?
– melpomene
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
AddLeaf returns a reference...
– Julian vD
Nov 15 '18 at 14:01
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
Yes, go on ...?
– melpomene
Nov 15 '18 at 14:03
|
show 2 more comments
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53320441%2freturning-shared-pointer-reference-breaks-outside-of-class-methods%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown