Assignment in C++ occurs despite exception on the right side

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
26
down vote

favorite
3












I have some (C++14) code that looks like this:



map<int, set<string>> junk;
for (int id : GenerateIds())
try
set<string> stuff = GetStuff();
junk[id] = stuff;
catch (const StuffException& e)
...




This works. Sometimes GetStuff() throws an exception, which works fine, because if it does, I don't want a value in the junk map then.



But at first I'd written this in the loop, which doesn't work:



junk[id] = GetStuff();


More precisely, even when GetStuff() throws an exception, junk[id] is created (and assigned an empty set).



This isn't what I'd expect: I'd expect them to function the same way.



Is there a principle of C++ that I've misunderstood here?










share|improve this question























  • Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
    – jww
    7 hours ago











  • See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
    – Shafik Yaghmour
    6 hours ago






  • 2




    Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
    – MSalters
    5 hours ago










  • @MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
    – jma
    4 hours ago














up vote
26
down vote

favorite
3












I have some (C++14) code that looks like this:



map<int, set<string>> junk;
for (int id : GenerateIds())
try
set<string> stuff = GetStuff();
junk[id] = stuff;
catch (const StuffException& e)
...




This works. Sometimes GetStuff() throws an exception, which works fine, because if it does, I don't want a value in the junk map then.



But at first I'd written this in the loop, which doesn't work:



junk[id] = GetStuff();


More precisely, even when GetStuff() throws an exception, junk[id] is created (and assigned an empty set).



This isn't what I'd expect: I'd expect them to function the same way.



Is there a principle of C++ that I've misunderstood here?










share|improve this question























  • Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
    – jww
    7 hours ago











  • See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
    – Shafik Yaghmour
    6 hours ago






  • 2




    Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
    – MSalters
    5 hours ago










  • @MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
    – jma
    4 hours ago












up vote
26
down vote

favorite
3









up vote
26
down vote

favorite
3






3





I have some (C++14) code that looks like this:



map<int, set<string>> junk;
for (int id : GenerateIds())
try
set<string> stuff = GetStuff();
junk[id] = stuff;
catch (const StuffException& e)
...




This works. Sometimes GetStuff() throws an exception, which works fine, because if it does, I don't want a value in the junk map then.



But at first I'd written this in the loop, which doesn't work:



junk[id] = GetStuff();


More precisely, even when GetStuff() throws an exception, junk[id] is created (and assigned an empty set).



This isn't what I'd expect: I'd expect them to function the same way.



Is there a principle of C++ that I've misunderstood here?










share|improve this question















I have some (C++14) code that looks like this:



map<int, set<string>> junk;
for (int id : GenerateIds())
try
set<string> stuff = GetStuff();
junk[id] = stuff;
catch (const StuffException& e)
...




This works. Sometimes GetStuff() throws an exception, which works fine, because if it does, I don't want a value in the junk map then.



But at first I'd written this in the loop, which doesn't work:



junk[id] = GetStuff();


More precisely, even when GetStuff() throws an exception, junk[id] is created (and assigned an empty set).



This isn't what I'd expect: I'd expect them to function the same way.



Is there a principle of C++ that I've misunderstood here?







c++ c++14






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 26 mins ago









Peter Mortensen

13.2k1983111




13.2k1983111










asked 7 hours ago









jma

1,11811531




1,11811531











  • Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
    – jww
    7 hours ago











  • See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
    – Shafik Yaghmour
    6 hours ago






  • 2




    Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
    – MSalters
    5 hours ago










  • @MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
    – jma
    4 hours ago
















  • Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
    – jww
    7 hours ago











  • See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
    – Shafik Yaghmour
    6 hours ago






  • 2




    Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
    – MSalters
    5 hours ago










  • @MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
    – jma
    4 hours ago















Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
– jww
7 hours ago





Also see c++ map exception safe insert and Making operations on standard-library containers strongly exception safe, Exception Safety: Concepts and Techniques, etc.
– jww
7 hours ago













See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
– Shafik Yaghmour
6 hours ago




See Order of evaluation of assignment statement in C++ also related Does this code from “The C++ Programming Language” 4th edition section 36.3.6 have well-defined behavior? and What are the evaluation order guarantees introduced by C++17?
– Shafik Yaghmour
6 hours ago




2




2




Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
– MSalters
5 hours ago




Just to clarify for future readers with similar problems: no assignment happens here. junk[id] creates a new set, yes, but that is using the default constructor. That's why the set is empty. This empty set would have been used as the object to assign to, if GetStuff() would have succeeded. But the exception thrown is precisely why no assignment happens. The set is left in its default state. It is a proper C++ object, and you can call its members normally. I.e. junk[id].size() will be 0 afterwards.
– MSalters
5 hours ago












@MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
– jma
4 hours ago




@MSalters Good clarification! I used "assignment" too loosely (but "default constructed" was maybe a bit heavy for the question title ;-).
– jma
4 hours ago












3 Answers
3






active

oldest

votes

















up vote
40
down vote



accepted










Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.



It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).



That means the evaluation order is implementation-defined, which means your compiler performs the evaluation of the left-hand side first.



See this evaluation order reference for more details (especially point 20).






share|improve this answer
















  • 1




    If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
    – Hans Olsson
    6 hours ago






  • 7




    "That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
    – geza
    5 hours ago

















up vote
7
down vote














std::map::operator



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.




junk[id] causes the above mentioned insertion and after that has already happened GetStuff() throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff(); may not do the insertion if GetStuff() throws.






share|improve this answer


















  • 2




    You're missing the part that explains why this happens even if the RHS throws.
    – juanchopanza
    7 hours ago










  • Is it guaranteed that the key is created if the RHS throws?
    – perreal
    7 hours ago










  • @juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
    – Ted Lyngmo
    7 hours ago






  • 1




    @perreal No, see Some programmer dudes answer.
    – Ted Lyngmo
    7 hours ago






  • 1




    @TedLyngmo Much better, thanks!
    – juanchopanza
    6 hours ago

















up vote
1
down vote













You're misunderstanding how operator works on std::map.



It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator= to set a new value.



To make this work the way you expect, you'll need to use std::map::insert (*):



junk.insert(std::make_pair(id, GetStuff()));


Caveat: insert will only add the value if id is not already mapped.






share|improve this answer
















  • 3




    i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
    – user463035818
    7 hours ago










  • If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
    – Hans Olsson
    5 hours ago










  • @user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
    – user2357112
    2 hours ago










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',
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
);



);













 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53154843%2fassignment-in-c-occurs-despite-exception-on-the-right-side%23new-answer', 'question_page');

);

Post as a guest






























3 Answers
3






active

oldest

votes








3 Answers
3






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
40
down vote



accepted










Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.



It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).



That means the evaluation order is implementation-defined, which means your compiler performs the evaluation of the left-hand side first.



See this evaluation order reference for more details (especially point 20).






share|improve this answer
















  • 1




    If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
    – Hans Olsson
    6 hours ago






  • 7




    "That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
    – geza
    5 hours ago














up vote
40
down vote



accepted










Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.



It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).



That means the evaluation order is implementation-defined, which means your compiler performs the evaluation of the left-hand side first.



See this evaluation order reference for more details (especially point 20).






share|improve this answer
















  • 1




    If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
    – Hans Olsson
    6 hours ago






  • 7




    "That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
    – geza
    5 hours ago












up vote
40
down vote



accepted







up vote
40
down vote



accepted






Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.



It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).



That means the evaluation order is implementation-defined, which means your compiler performs the evaluation of the left-hand side first.



See this evaluation order reference for more details (especially point 20).






share|improve this answer












Before C++17 there was no sequencing between the left- and right-hand side of overloaded assignment operators.



It's first in C++17 that explicit sequencing was introduced (right-hand side is evaluated first).



That means the evaluation order is implementation-defined, which means your compiler performs the evaluation of the left-hand side first.



See this evaluation order reference for more details (especially point 20).







share|improve this answer












share|improve this answer



share|improve this answer










answered 7 hours ago









Some programmer dude

288k24239398




288k24239398







  • 1




    If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
    – Hans Olsson
    6 hours ago






  • 7




    "That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
    – geza
    5 hours ago












  • 1




    If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
    – Hans Olsson
    6 hours ago






  • 7




    "That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
    – geza
    5 hours ago







1




1




If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
– Hans Olsson
6 hours ago




If I understand the reference correctly the first sentence in the answer could be shortened by removing "overloaded", as right-hand-side is evaluated first for both overloaded and non-overloaded assignment operators in C++17.
– Hans Olsson
6 hours ago




7




7




"That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
– geza
5 hours ago




"That means the evaluation order is implementation-defined". Isn't it more correct to say that "evaluation order is unspecified in C++14 and before"?
– geza
5 hours ago












up vote
7
down vote














std::map::operator



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.




junk[id] causes the above mentioned insertion and after that has already happened GetStuff() throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff(); may not do the insertion if GetStuff() throws.






share|improve this answer


















  • 2




    You're missing the part that explains why this happens even if the RHS throws.
    – juanchopanza
    7 hours ago










  • Is it guaranteed that the key is created if the RHS throws?
    – perreal
    7 hours ago










  • @juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
    – Ted Lyngmo
    7 hours ago






  • 1




    @perreal No, see Some programmer dudes answer.
    – Ted Lyngmo
    7 hours ago






  • 1




    @TedLyngmo Much better, thanks!
    – juanchopanza
    6 hours ago














up vote
7
down vote














std::map::operator



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.




junk[id] causes the above mentioned insertion and after that has already happened GetStuff() throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff(); may not do the insertion if GetStuff() throws.






share|improve this answer


















  • 2




    You're missing the part that explains why this happens even if the RHS throws.
    – juanchopanza
    7 hours ago










  • Is it guaranteed that the key is created if the RHS throws?
    – perreal
    7 hours ago










  • @juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
    – Ted Lyngmo
    7 hours ago






  • 1




    @perreal No, see Some programmer dudes answer.
    – Ted Lyngmo
    7 hours ago






  • 1




    @TedLyngmo Much better, thanks!
    – juanchopanza
    6 hours ago












up vote
7
down vote










up vote
7
down vote










std::map::operator



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.




junk[id] causes the above mentioned insertion and after that has already happened GetStuff() throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff(); may not do the insertion if GetStuff() throws.






share|improve this answer















std::map::operator



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.




junk[id] causes the above mentioned insertion and after that has already happened GetStuff() throws. Note that in C++14 the order in which these things happen is implementation defined so with a different compiler your junk[id] = GetStuff(); may not do the insertion if GetStuff() throws.







share|improve this answer














share|improve this answer



share|improve this answer








edited 6 hours ago

























answered 7 hours ago









Ted Lyngmo

36915




36915







  • 2




    You're missing the part that explains why this happens even if the RHS throws.
    – juanchopanza
    7 hours ago










  • Is it guaranteed that the key is created if the RHS throws?
    – perreal
    7 hours ago










  • @juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
    – Ted Lyngmo
    7 hours ago






  • 1




    @perreal No, see Some programmer dudes answer.
    – Ted Lyngmo
    7 hours ago






  • 1




    @TedLyngmo Much better, thanks!
    – juanchopanza
    6 hours ago












  • 2




    You're missing the part that explains why this happens even if the RHS throws.
    – juanchopanza
    7 hours ago










  • Is it guaranteed that the key is created if the RHS throws?
    – perreal
    7 hours ago










  • @juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
    – Ted Lyngmo
    7 hours ago






  • 1




    @perreal No, see Some programmer dudes answer.
    – Ted Lyngmo
    7 hours ago






  • 1




    @TedLyngmo Much better, thanks!
    – juanchopanza
    6 hours ago







2




2




You're missing the part that explains why this happens even if the RHS throws.
– juanchopanza
7 hours ago




You're missing the part that explains why this happens even if the RHS throws.
– juanchopanza
7 hours ago












Is it guaranteed that the key is created if the RHS throws?
– perreal
7 hours ago




Is it guaranteed that the key is created if the RHS throws?
– perreal
7 hours ago












@juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
– Ted Lyngmo
7 hours ago




@juanchopanza "junk[id] causes this" was referring to the text I quoted and "and then GetStuff() throws" was referring to what happens after the insertion has already taken place. Perhaps I could been clearer. Will edit.
– Ted Lyngmo
7 hours ago




1




1




@perreal No, see Some programmer dudes answer.
– Ted Lyngmo
7 hours ago




@perreal No, see Some programmer dudes answer.
– Ted Lyngmo
7 hours ago




1




1




@TedLyngmo Much better, thanks!
– juanchopanza
6 hours ago




@TedLyngmo Much better, thanks!
– juanchopanza
6 hours ago










up vote
1
down vote













You're misunderstanding how operator works on std::map.



It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator= to set a new value.



To make this work the way you expect, you'll need to use std::map::insert (*):



junk.insert(std::make_pair(id, GetStuff()));


Caveat: insert will only add the value if id is not already mapped.






share|improve this answer
















  • 3




    i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
    – user463035818
    7 hours ago










  • If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
    – Hans Olsson
    5 hours ago










  • @user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
    – user2357112
    2 hours ago














up vote
1
down vote













You're misunderstanding how operator works on std::map.



It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator= to set a new value.



To make this work the way you expect, you'll need to use std::map::insert (*):



junk.insert(std::make_pair(id, GetStuff()));


Caveat: insert will only add the value if id is not already mapped.






share|improve this answer
















  • 3




    i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
    – user463035818
    7 hours ago










  • If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
    – Hans Olsson
    5 hours ago










  • @user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
    – user2357112
    2 hours ago












up vote
1
down vote










up vote
1
down vote









You're misunderstanding how operator works on std::map.



It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator= to set a new value.



To make this work the way you expect, you'll need to use std::map::insert (*):



junk.insert(std::make_pair(id, GetStuff()));


Caveat: insert will only add the value if id is not already mapped.






share|improve this answer












You're misunderstanding how operator works on std::map.



It returns a reference to the mapped item. Therefore, your code is first inserting a default item in that position and then invoking operator= to set a new value.



To make this work the way you expect, you'll need to use std::map::insert (*):



junk.insert(std::make_pair(id, GetStuff()));


Caveat: insert will only add the value if id is not already mapped.







share|improve this answer












share|improve this answer



share|improve this answer










answered 7 hours ago









paddy

41.2k52874




41.2k52874







  • 3




    i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
    – user463035818
    7 hours ago










  • If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
    – Hans Olsson
    5 hours ago










  • @user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
    – user2357112
    2 hours ago












  • 3




    i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
    – user463035818
    7 hours ago










  • If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
    – Hans Olsson
    5 hours ago










  • @user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
    – user2357112
    2 hours ago







3




3




i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
– user463035818
7 hours ago




i dont think there is any misconception about how operator works involved here. Also from your answer its not clear why operator= evaluates the left hand side, even if the right hand side throws an exception
– user463035818
7 hours ago












If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
– Hans Olsson
5 hours ago




If there is any misunderstanding, it would for me be a misunderstanding for a[b]=...; not just for a[...].
– Hans Olsson
5 hours ago












@user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
– user2357112
2 hours ago




@user463035818: The questioner expresses a belief that an assignment occurred, which strongly suggests they are unaware that evaluating the operator would create an empty set for junk[id] on its own.
– user2357112
2 hours ago

















 

draft saved


draft discarded















































 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53154843%2fassignment-in-c-occurs-despite-exception-on-the-right-side%23new-answer', 'question_page');

);

Post as a guest













































































Comments

Popular posts from this blog

Long meetings (6-7 hours a day): Being “babysat” by supervisor

Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

Confectionery