Are there situations when self-assignment is useful?What is a smart pointer and when should I use one?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?When to use virtual destructors?relation between access specifiers and using initializer lists for POD types in c++0xPlain Old Data types with private members?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?Does the default assignment operator call operator= on all members?Assignment Operator for an objectPOD structs containing constant memberDeleted implicitly-declared copy assignment operator
Why did the World Bank set the global poverty line at $1.90?
Transfer custom ringtones to iPhone using a computer running Linux
Why ambiguous grammars are bad?
What's the meaning of the expression "short circuit" in the text bellow?
Tikz-cd diagram arrow passing under a node - not crossing it
How durable are silver inlays on a blade?
Multiband vertical antenna not working as expected
C++ logging library
Grep Match and extract
What STL algorithm can determine if exactly one item in a container satisfies a predicate?
Was planting UN flag on Moon ever discussed?
Do empty drive bays need to be filled?
Are the guests in Westworld forbidden to tell the hosts that they are robots?
Extracting data from Plot
Assigning function to function pointer, const argument correctness?
If there's something that implicates the president why is there then a national security issue? (John Dowd)
Is Dumbledore a human lie detector?
I've been given a project I can't complete, what should I do?
bash vs. zsh: What are the practical differences?
Can the removal of a duty-free sales trolley result in a measurable reduction in emissions?
Difference templates and layouts
Why isn't Bash trap working if output is redirected to stdout?
Is the Keras Embedding layer dependent on the target label?
Why are MBA programs closing in the United States?
Are there situations when self-assignment is useful?
What is a smart pointer and when should I use one?When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?When to use virtual destructors?relation between access specifiers and using initializer lists for POD types in c++0xPlain Old Data types with private members?Why don't Java's +=, -=, *=, /= compound assignment operators require casting?Does the default assignment operator call operator= on all members?Assignment Operator for an objectPOD structs containing constant memberDeleted implicitly-declared copy assignment operator
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
It is commonly known that when implementing an assignment operator one has to protect against self-assignment, at least when the class has non-POD members. Usually it is (or is equivalent to):
Foo& operator=(const Foo& other)
if (&other == this)
return *this;
... // Do copy
What were the reasons for not inserting the self-assignment protection automatically? Are there use cases when self-assignment does something non-trivial and practically useful?
Foo& operator=(const Foo& other)
if (&other == this)
// Do something non-trivial
else
// Do copy
return *this;
To summarize the answers and discussion by now
Looks like non-trivial self-assignment can never be really useful. The only option proposed was to put an assert
there in order to detect some logical errors. But there are quite legitimate self-assignment cases like a = std::min(a, b)
, so even this option is highly dubious.
But there are two possible implementations of a trivial self-assignment:
- Do nothing if
&other == this
. Always work, though may have negative performance impact due to an extra branching. But in a user-defined assignment operator the test must be almost always explicitly made. - Copy each member to itself. This is what is done by default. If the members use default assignment operators as well, it may be faster, because doesn't requre an extra branching.
I still don't see why the C++ standard could not guarantee that in a user-defined assignment operator &other != this
. If you want no branching, use the default operator. If you are redefining the operator, some test is needed anyway...
c++ assignment-operator
|
show 7 more comments
It is commonly known that when implementing an assignment operator one has to protect against self-assignment, at least when the class has non-POD members. Usually it is (or is equivalent to):
Foo& operator=(const Foo& other)
if (&other == this)
return *this;
... // Do copy
What were the reasons for not inserting the self-assignment protection automatically? Are there use cases when self-assignment does something non-trivial and practically useful?
Foo& operator=(const Foo& other)
if (&other == this)
// Do something non-trivial
else
// Do copy
return *this;
To summarize the answers and discussion by now
Looks like non-trivial self-assignment can never be really useful. The only option proposed was to put an assert
there in order to detect some logical errors. But there are quite legitimate self-assignment cases like a = std::min(a, b)
, so even this option is highly dubious.
But there are two possible implementations of a trivial self-assignment:
- Do nothing if
&other == this
. Always work, though may have negative performance impact due to an extra branching. But in a user-defined assignment operator the test must be almost always explicitly made. - Copy each member to itself. This is what is done by default. If the members use default assignment operators as well, it may be faster, because doesn't requre an extra branching.
I still don't see why the C++ standard could not guarantee that in a user-defined assignment operator &other != this
. If you want no branching, use the default operator. If you are redefining the operator, some test is needed anyway...
c++ assignment-operator
3
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
5
Well, the C++ standard library is crazy enough to overload<<
and>>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with=
.
– melpomene
May 26 at 18:39
7
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
3
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
2
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59
|
show 7 more comments
It is commonly known that when implementing an assignment operator one has to protect against self-assignment, at least when the class has non-POD members. Usually it is (or is equivalent to):
Foo& operator=(const Foo& other)
if (&other == this)
return *this;
... // Do copy
What were the reasons for not inserting the self-assignment protection automatically? Are there use cases when self-assignment does something non-trivial and practically useful?
Foo& operator=(const Foo& other)
if (&other == this)
// Do something non-trivial
else
// Do copy
return *this;
To summarize the answers and discussion by now
Looks like non-trivial self-assignment can never be really useful. The only option proposed was to put an assert
there in order to detect some logical errors. But there are quite legitimate self-assignment cases like a = std::min(a, b)
, so even this option is highly dubious.
But there are two possible implementations of a trivial self-assignment:
- Do nothing if
&other == this
. Always work, though may have negative performance impact due to an extra branching. But in a user-defined assignment operator the test must be almost always explicitly made. - Copy each member to itself. This is what is done by default. If the members use default assignment operators as well, it may be faster, because doesn't requre an extra branching.
I still don't see why the C++ standard could not guarantee that in a user-defined assignment operator &other != this
. If you want no branching, use the default operator. If you are redefining the operator, some test is needed anyway...
c++ assignment-operator
It is commonly known that when implementing an assignment operator one has to protect against self-assignment, at least when the class has non-POD members. Usually it is (or is equivalent to):
Foo& operator=(const Foo& other)
if (&other == this)
return *this;
... // Do copy
What were the reasons for not inserting the self-assignment protection automatically? Are there use cases when self-assignment does something non-trivial and practically useful?
Foo& operator=(const Foo& other)
if (&other == this)
// Do something non-trivial
else
// Do copy
return *this;
To summarize the answers and discussion by now
Looks like non-trivial self-assignment can never be really useful. The only option proposed was to put an assert
there in order to detect some logical errors. But there are quite legitimate self-assignment cases like a = std::min(a, b)
, so even this option is highly dubious.
But there are two possible implementations of a trivial self-assignment:
- Do nothing if
&other == this
. Always work, though may have negative performance impact due to an extra branching. But in a user-defined assignment operator the test must be almost always explicitly made. - Copy each member to itself. This is what is done by default. If the members use default assignment operators as well, it may be faster, because doesn't requre an extra branching.
I still don't see why the C++ standard could not guarantee that in a user-defined assignment operator &other != this
. If you want no branching, use the default operator. If you are redefining the operator, some test is needed anyway...
c++ assignment-operator
c++ assignment-operator
edited May 29 at 20:25
aparpara
asked May 26 at 18:27
aparparaaparpara
882117
882117
3
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
5
Well, the C++ standard library is crazy enough to overload<<
and>>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with=
.
– melpomene
May 26 at 18:39
7
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
3
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
2
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59
|
show 7 more comments
3
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
5
Well, the C++ standard library is crazy enough to overload<<
and>>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with=
.
– melpomene
May 26 at 18:39
7
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
3
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
2
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59
3
3
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
5
5
Well, the C++ standard library is crazy enough to overload
<<
and >>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with =
.– melpomene
May 26 at 18:39
Well, the C++ standard library is crazy enough to overload
<<
and >>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with =
.– melpomene
May 26 at 18:39
7
7
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
3
3
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
2
2
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59
|
show 7 more comments
3 Answers
3
active
oldest
votes
Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.
So it's not about self-assignment being useful; it's about self-assignment not always needing protection.
Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos likefoo[i] = foo[i]
instead offoo[i] = foo[j]
or similar problems happen ridiculously often.
– VTT
May 26 at 18:50
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
add a comment |
There are algorithms where it can happen.
You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider
a = std::min(a,b);
- simpler and perhaps easier to understand thanif (a > b) a = b;
- now consider more complicated examples of similar things.You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.
These algorithms where it can happen are not uncommon.
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparinga
andb
and then possibly branch when checking for self assignment instead of just a single branching.
– VTT
May 26 at 18:54
add a comment |
I should admit I have never heard about the common knowledge like this. For a non-POD objects, a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator. So that you don't have the problem at all.
If you still need to copy the class, but there is some data which is unsafe to copy to itself, you could only override assignment for that data, and when it is used as a field, it would be used by an automatic assignment implementation of the upper level class.
As for your question, if you only need to skip doing anything the automatic "self-assignment protection" is there already, in a way. If you don't define assignment operation explicitely and let compiler use the automatic one, after inlining self-assignment may become no-op.
For example, the following code:
class A
int a;
double b;
;
A& foo(A& input)
return (input = input);
is compiled to (gcc 4.9, -O2):
_Z3fooR1A:
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc
Which does not copy anything.
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
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%2f56316291%2fare-there-situations-when-self-assignment-is-useful%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.
So it's not about self-assignment being useful; it's about self-assignment not always needing protection.
Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos likefoo[i] = foo[i]
instead offoo[i] = foo[j]
or similar problems happen ridiculously often.
– VTT
May 26 at 18:50
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
add a comment |
Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.
So it's not about self-assignment being useful; it's about self-assignment not always needing protection.
Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos likefoo[i] = foo[i]
instead offoo[i] = foo[j]
or similar problems happen ridiculously often.
– VTT
May 26 at 18:50
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
add a comment |
Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.
So it's not about self-assignment being useful; it's about self-assignment not always needing protection.
Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.
Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself. Consider the case where you have a user-provided assignment operator because each individual object has some kind of identifier, which you don't want to copy. Well, you can "copy" the other values just fine in self-assignment cases. So inserting an invisible self-assignment test is just adding a pointless and potentially costly conditional branch.
So it's not about self-assignment being useful; it's about self-assignment not always needing protection.
Furthermore, C++ generally doesn't like adding code like that to your code without you explicitly asking for it. It's typically done in terms of whole functions, not part of functions. Even destructor calls at the end of blocks are something you asked for when you put the object to be destroyed on the stack.
answered May 26 at 18:41
Nicol BolasNicol Bolas
298k35497673
298k35497673
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos likefoo[i] = foo[i]
instead offoo[i] = foo[j]
or similar problems happen ridiculously often.
– VTT
May 26 at 18:50
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
add a comment |
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos likefoo[i] = foo[i]
instead offoo[i] = foo[j]
or similar problems happen ridiculously often.
– VTT
May 26 at 18:50
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
2
2
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos like
foo[i] = foo[i]
instead of foo[i] = foo[j]
or similar problems happen ridiculously often.– VTT
May 26 at 18:50
OP was asking about a situation when self assignment would be useful, not about whether self-assignment protection is necessary or when it should be implemented. Also I have to disagree with "Self-assignment protection is only necessary for types where the code being skipped is dangerous when applied to itself." Such a check can be very helpful even if self-assignment itself is completely harmless to catch problems in calling code. Typos like
foo[i] = foo[i]
instead of foo[i] = foo[j]
or similar problems happen ridiculously often.– VTT
May 26 at 18:50
6
6
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
@VTT: The second sentence of the post is "What was the reasons for not inserting the self-assignment protection automatically?" The principle question only exists because of the assumption that this automatic protection would have been there if there wasn't some utility for the concept of self-assignment. My post counters this assumption, and once countered, the question becomes irrelevant.
– Nicol Bolas
May 26 at 19:09
1
1
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
@VTT "Typos like foo[i] = foo[i] instead of foo[i] = foo[j]" the provided approach does not report the typo so it is unclear how it can help fixing them.
– max630
May 27 at 3:35
add a comment |
There are algorithms where it can happen.
You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider
a = std::min(a,b);
- simpler and perhaps easier to understand thanif (a > b) a = b;
- now consider more complicated examples of similar things.You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.
These algorithms where it can happen are not uncommon.
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparinga
andb
and then possibly branch when checking for self assignment instead of just a single branching.
– VTT
May 26 at 18:54
add a comment |
There are algorithms where it can happen.
You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider
a = std::min(a,b);
- simpler and perhaps easier to understand thanif (a > b) a = b;
- now consider more complicated examples of similar things.You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.
These algorithms where it can happen are not uncommon.
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparinga
andb
and then possibly branch when checking for self assignment instead of just a single branching.
– VTT
May 26 at 18:54
add a comment |
There are algorithms where it can happen.
You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider
a = std::min(a,b);
- simpler and perhaps easier to understand thanif (a > b) a = b;
- now consider more complicated examples of similar things.You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.
These algorithms where it can happen are not uncommon.
There are algorithms where it can happen.
You know the lhs and rhs might be the same but it is just simpler to do the assignment than check. E.g., consider
a = std::min(a,b);
- simpler and perhaps easier to understand thanif (a > b) a = b;
- now consider more complicated examples of similar things.You don't know whether lhs and rhs might be the same, because they may have been passed in from somewhere else.
These algorithms where it can happen are not uncommon.
edited May 26 at 18:48
Jesper Juhl
1
1
answered May 26 at 18:46
davidbakdavidbak
2,87122037
2,87122037
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparinga
andb
and then possibly branch when checking for self assignment instead of just a single branching.
– VTT
May 26 at 18:54
add a comment |
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparinga
andb
and then possibly branch when checking for self assignment instead of just a single branching.
– VTT
May 26 at 18:54
2
2
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
The question was about a non-trivial self-assignment.
– aparpara
May 26 at 18:50
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparing
a
and b
and then possibly branch when checking for self assignment instead of just a single branching.– VTT
May 26 at 18:54
I'd say the possibly handled self assignment makes case (1) more complicated, because we first need to branch when comparing
a
and b
and then possibly branch when checking for self assignment instead of just a single branching.– VTT
May 26 at 18:54
add a comment |
I should admit I have never heard about the common knowledge like this. For a non-POD objects, a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator. So that you don't have the problem at all.
If you still need to copy the class, but there is some data which is unsafe to copy to itself, you could only override assignment for that data, and when it is used as a field, it would be used by an automatic assignment implementation of the upper level class.
As for your question, if you only need to skip doing anything the automatic "self-assignment protection" is there already, in a way. If you don't define assignment operation explicitely and let compiler use the automatic one, after inlining self-assignment may become no-op.
For example, the following code:
class A
int a;
double b;
;
A& foo(A& input)
return (input = input);
is compiled to (gcc 4.9, -O2):
_Z3fooR1A:
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc
Which does not copy anything.
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
add a comment |
I should admit I have never heard about the common knowledge like this. For a non-POD objects, a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator. So that you don't have the problem at all.
If you still need to copy the class, but there is some data which is unsafe to copy to itself, you could only override assignment for that data, and when it is used as a field, it would be used by an automatic assignment implementation of the upper level class.
As for your question, if you only need to skip doing anything the automatic "self-assignment protection" is there already, in a way. If you don't define assignment operation explicitely and let compiler use the automatic one, after inlining self-assignment may become no-op.
For example, the following code:
class A
int a;
double b;
;
A& foo(A& input)
return (input = input);
is compiled to (gcc 4.9, -O2):
_Z3fooR1A:
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc
Which does not copy anything.
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
add a comment |
I should admit I have never heard about the common knowledge like this. For a non-POD objects, a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator. So that you don't have the problem at all.
If you still need to copy the class, but there is some data which is unsafe to copy to itself, you could only override assignment for that data, and when it is used as a field, it would be used by an automatic assignment implementation of the upper level class.
As for your question, if you only need to skip doing anything the automatic "self-assignment protection" is there already, in a way. If you don't define assignment operation explicitely and let compiler use the automatic one, after inlining self-assignment may become no-op.
For example, the following code:
class A
int a;
double b;
;
A& foo(A& input)
return (input = input);
is compiled to (gcc 4.9, -O2):
_Z3fooR1A:
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc
Which does not copy anything.
I should admit I have never heard about the common knowledge like this. For a non-POD objects, a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator. So that you don't have the problem at all.
If you still need to copy the class, but there is some data which is unsafe to copy to itself, you could only override assignment for that data, and when it is used as a field, it would be used by an automatic assignment implementation of the upper level class.
As for your question, if you only need to skip doing anything the automatic "self-assignment protection" is there already, in a way. If you don't define assignment operation explicitely and let compiler use the automatic one, after inlining self-assignment may become no-op.
For example, the following code:
class A
int a;
double b;
;
A& foo(A& input)
return (input = input);
is compiled to (gcc 4.9, -O2):
_Z3fooR1A:
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc
Which does not copy anything.
answered May 27 at 3:39
max630max630
5,57211542
5,57211542
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
add a comment |
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
1
1
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
"a more strict approach is to forbid copying them with disabling copy constructor and the assignment operator." And what about moving? Note that the OP was not specific about the form of self-assignment: copy or move. While lots of more complex types can't reasonably be copied, few are the types that cannot logically be moved.
– Nicol Bolas
May 27 at 4:20
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
@NicolBolas the OP's code uses copying, and I meant there copying. I guess for moving next paragraphs apply as well.
– max630
May 27 at 5:03
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%2f56316291%2fare-there-situations-when-self-assignment-is-useful%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
This is an interesting question. I would even say that typically self-assignment is an indicator of some sort of logic error and it makes sense to use an assertion or other form of strict check. I can definitely imagine it being harmless, but not useful.
– VTT
May 26 at 18:31
5
Well, the C++ standard library is crazy enough to overload
<<
and>>
with effectful operations. Maybe they figured someone might want to do similarly crazy things with=
.– melpomene
May 26 at 18:39
7
The conditional branch may make "check and maybe do nothing" slower than "just do it", so the check should not be done by default.
– molbdnilo
May 26 at 18:45
3
I can also imagine situations where you want to know how often it happens, perhaps for performance reasons. If the language were to "hide" self-assignments, this would be difficult to analyse.
– molbdnilo
May 26 at 18:52
2
You might find this to be an interesting read: ericniebler.com/2017/03/31/post-conditions-on-self-move
– chris
May 26 at 18:59