Delayed instantiation in C++
I'm trying to create a variable without instantiating the object.
In Python it would look like this:
graph = mymap[c] if c in mymap else Graph()
So I basically check if I already have that graph otherwise I create it. My understanding is that if I declare the following in C++ it will call the constructor and be wasteful.
Graph g;
So I'm trying to use pointers to avoid this "waste":
Graph* g;
if (graphs.find(c) == graphs.end()){
g = new Graph();
graphs[c] = *g;
} else {
g = &(graphs[c]);
}
std::cout << g << std::endl;
std::cout << &(graphs[c]) << std::endl;
The problem is that the addresses printed in the end do not match. In fact, my tests show that something weird is happening like a new instance of Graph is being created every time.
What am I doing wrong?
c++
add a comment |
I'm trying to create a variable without instantiating the object.
In Python it would look like this:
graph = mymap[c] if c in mymap else Graph()
So I basically check if I already have that graph otherwise I create it. My understanding is that if I declare the following in C++ it will call the constructor and be wasteful.
Graph g;
So I'm trying to use pointers to avoid this "waste":
Graph* g;
if (graphs.find(c) == graphs.end()){
g = new Graph();
graphs[c] = *g;
} else {
g = &(graphs[c]);
}
std::cout << g << std::endl;
std::cout << &(graphs[c]) << std::endl;
The problem is that the addresses printed in the end do not match. In fact, my tests show that something weird is happening like a new instance of Graph is being created every time.
What am I doing wrong?
c++
3
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
1
Could you complete the example, showing the type ofc
and ofgraphs
(the latter presumably anstd::map
orstd::unordered_map
?
– jwimberley
Nov 20 '18 at 22:36
1
There are better solutions, as detailed in 1+ answers, but to clarify:graphs[c] = *g
is not doing what you think it is.
– jwimberley
Nov 20 '18 at 22:39
add a comment |
I'm trying to create a variable without instantiating the object.
In Python it would look like this:
graph = mymap[c] if c in mymap else Graph()
So I basically check if I already have that graph otherwise I create it. My understanding is that if I declare the following in C++ it will call the constructor and be wasteful.
Graph g;
So I'm trying to use pointers to avoid this "waste":
Graph* g;
if (graphs.find(c) == graphs.end()){
g = new Graph();
graphs[c] = *g;
} else {
g = &(graphs[c]);
}
std::cout << g << std::endl;
std::cout << &(graphs[c]) << std::endl;
The problem is that the addresses printed in the end do not match. In fact, my tests show that something weird is happening like a new instance of Graph is being created every time.
What am I doing wrong?
c++
I'm trying to create a variable without instantiating the object.
In Python it would look like this:
graph = mymap[c] if c in mymap else Graph()
So I basically check if I already have that graph otherwise I create it. My understanding is that if I declare the following in C++ it will call the constructor and be wasteful.
Graph g;
So I'm trying to use pointers to avoid this "waste":
Graph* g;
if (graphs.find(c) == graphs.end()){
g = new Graph();
graphs[c] = *g;
} else {
g = &(graphs[c]);
}
std::cout << g << std::endl;
std::cout << &(graphs[c]) << std::endl;
The problem is that the addresses printed in the end do not match. In fact, my tests show that something weird is happening like a new instance of Graph is being created every time.
What am I doing wrong?
c++
c++
asked Nov 20 '18 at 22:33
RafaelRafael
345310
345310
3
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
1
Could you complete the example, showing the type ofc
and ofgraphs
(the latter presumably anstd::map
orstd::unordered_map
?
– jwimberley
Nov 20 '18 at 22:36
1
There are better solutions, as detailed in 1+ answers, but to clarify:graphs[c] = *g
is not doing what you think it is.
– jwimberley
Nov 20 '18 at 22:39
add a comment |
3
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
1
Could you complete the example, showing the type ofc
and ofgraphs
(the latter presumably anstd::map
orstd::unordered_map
?
– jwimberley
Nov 20 '18 at 22:36
1
There are better solutions, as detailed in 1+ answers, but to clarify:graphs[c] = *g
is not doing what you think it is.
– jwimberley
Nov 20 '18 at 22:39
3
3
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
1
1
Could you complete the example, showing the type of
c
and of graphs
(the latter presumably an std::map
or std::unordered_map
?– jwimberley
Nov 20 '18 at 22:36
Could you complete the example, showing the type of
c
and of graphs
(the latter presumably an std::map
or std::unordered_map
?– jwimberley
Nov 20 '18 at 22:36
1
1
There are better solutions, as detailed in 1+ answers, but to clarify:
graphs[c] = *g
is not doing what you think it is.– jwimberley
Nov 20 '18 at 22:39
There are better solutions, as detailed in 1+ answers, but to clarify:
graphs[c] = *g
is not doing what you think it is.– jwimberley
Nov 20 '18 at 22:39
add a comment |
2 Answers
2
active
oldest
votes
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator
has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
Even better, it could just be Graph& g = graphs[c], where graphs callsGraph
's default constructor, and no memory management is needed.
– jwimberley
Nov 20 '18 at 22:37
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just doGraph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.
– Rafael
Nov 20 '18 at 22:45
2
Graph g = graphs[c];
would copy. Probably not what you're after.
– user4581301
Nov 20 '18 at 22:46
add a comment |
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new
that g
points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c
already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new
.
add a comment |
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%2f53402594%2fdelayed-instantiation-in-c%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator
has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
Even better, it could just be Graph& g = graphs[c], where graphs callsGraph
's default constructor, and no memory management is needed.
– jwimberley
Nov 20 '18 at 22:37
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just doGraph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.
– Rafael
Nov 20 '18 at 22:45
2
Graph g = graphs[c];
would copy. Probably not what you're after.
– user4581301
Nov 20 '18 at 22:46
add a comment |
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator
has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
Even better, it could just be Graph& g = graphs[c], where graphs callsGraph
's default constructor, and no memory management is needed.
– jwimberley
Nov 20 '18 at 22:37
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just doGraph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.
– Rafael
Nov 20 '18 at 22:45
2
Graph g = graphs[c];
would copy. Probably not what you're after.
– user4581301
Nov 20 '18 at 22:46
add a comment |
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator
has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
You actually don't have to do anything fancy here. You can simply do
Graph* g = &graphs[c];
The reason is that map::operator
has the following behavior:
Returns a reference to the value that is mapped to a key equivalent to key, performing an insertion if such key does not already exist.
So if the key has an associated value already, you'll get a reference to that object. If that key does not yet exist, a value will be default constructed and inserted for you, and a reference to that new object will be returned.
answered Nov 20 '18 at 22:36


CoryKramerCoryKramer
74k1188141
74k1188141
Even better, it could just be Graph& g = graphs[c], where graphs callsGraph
's default constructor, and no memory management is needed.
– jwimberley
Nov 20 '18 at 22:37
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just doGraph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.
– Rafael
Nov 20 '18 at 22:45
2
Graph g = graphs[c];
would copy. Probably not what you're after.
– user4581301
Nov 20 '18 at 22:46
add a comment |
Even better, it could just be Graph& g = graphs[c], where graphs callsGraph
's default constructor, and no memory management is needed.
– jwimberley
Nov 20 '18 at 22:37
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just doGraph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.
– Rafael
Nov 20 '18 at 22:45
2
Graph g = graphs[c];
would copy. Probably not what you're after.
– user4581301
Nov 20 '18 at 22:46
Even better, it could just be Graph& g = graphs[c], where graphs calls
Graph
's default constructor, and no memory management is needed.– jwimberley
Nov 20 '18 at 22:37
Even better, it could just be Graph& g = graphs[c], where graphs calls
Graph
's default constructor, and no memory management is needed.– jwimberley
Nov 20 '18 at 22:37
1
1
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
That is exactly what my answer is stating, the only difference is whether you return a reference or a pointer, the allocation and construction is identical to what you demonstrated in your comment
– CoryKramer
Nov 20 '18 at 22:38
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Yeah, I get that, I was just making a comment to point out the extra niceties your suggestion provides, since the code in the OP's question is leaky...
– jwimberley
Nov 20 '18 at 22:41
Can I just do
Graph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.– Rafael
Nov 20 '18 at 22:45
Can I just do
Graph g = graphs[c];
? Would that be equivalent to the Python code? I started messing with pointers because I thought it was the only way.– Rafael
Nov 20 '18 at 22:45
2
2
Graph g = graphs[c];
would copy. Probably not what you're after.– user4581301
Nov 20 '18 at 22:46
Graph g = graphs[c];
would copy. Probably not what you're after.– user4581301
Nov 20 '18 at 22:46
add a comment |
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new
that g
points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c
already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new
.
add a comment |
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new
that g
points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c
already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new
.
add a comment |
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new
that g
points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c
already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new
.
Another answer already says the right way to do what you're asking, but I'll address (ha!) why the addresses don't match:
On this line:
graphs[c] = *g;
You're creating a COPY of the graph you just made with new
that g
points to, and that copy has a different address. You're then printing the address of the original and the address of the copy, so obviously they're at different addresses.
graphs[c] = ...
This code already does the allocation and construction of a (default) Graph object to be stored inside the map when there isn't one mapped to c
already (which you already checked for).. the assignment after that just makes the Graph object it just created look like the one that you had previously created with the call to new
.
edited Nov 20 '18 at 22:57
answered Nov 20 '18 at 22:42
xaxxonxaxxon
14.4k43060
14.4k43060
add a comment |
add a comment |
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%2f53402594%2fdelayed-instantiation-in-c%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
3
Maps already do this. You are allocating an object, then dereferencing it and copying it inside your map, leaking the allocation. Basically not doing what you think it does.
– Matthieu Brucher
Nov 20 '18 at 22:36
1
Could you complete the example, showing the type of
c
and ofgraphs
(the latter presumably anstd::map
orstd::unordered_map
?– jwimberley
Nov 20 '18 at 22:36
1
There are better solutions, as detailed in 1+ answers, but to clarify:
graphs[c] = *g
is not doing what you think it is.– jwimberley
Nov 20 '18 at 22:39