• Sign In / Suggest an Article

Current ISO C++ status

Upcoming ISO C++ meetings

Upcoming C++ conferences

Compiler conformance status

ISO C++ committee meeting

June 24-29, St. Louis, MO, USA

July 2-5, Folkestone, Kent, UK

assignment operators

Assignment operators, what is “self assignment”.

Self assignment is when someone assigns an object to itself. For example,

Obviously no one ever explicitly does a self assignment like the above, but since more than one pointer or reference can point to the same object (aliasing), it is possible to have self assignment without knowing it:

This is only valid for copy assignment. Self-assignment is not valid for move assignment.

Why should I worry about “self assignment”?

If you don’t worry about self assignment , you’ll expose your users to some very subtle bugs that have very subtle and often disastrous symptoms. For example, the following class will cause a complete disaster in the case of self-assignment:

If someone assigns a Fred object to itself, line #1 deletes both this->p_ and f.p_ since *this and f are the same object. But line #2 uses *f.p_ , which is no longer a valid object. This will likely cause a major disaster.

The bottom line is that you the author of class Fred are responsible to make sure self-assignment on a Fred object is innocuous . Do not assume that users won’t ever do that to your objects. It is your fault if your object crashes when it gets a self-assignment.

Aside: the above Fred::operator= (const Fred&) has a second problem: If an exception is thrown while evaluating new Wilma(*f.p_) (e.g., an out-of-memory exception or an exception in Wilma ’s copy constructor ), this->p_ will be a dangling pointer — it will point to memory that is no longer valid. This can be solved by allocating the new objects before deleting the old objects.

Okay, okay, already; I’ll handle self-assignment. How do I do it?

You should worry about self assignment every time you create a class . This does not mean that you need to add extra code to all your classes: as long as your objects gracefully handle self assignment, it doesn’t matter whether you had to add extra code or not.

We will illustrate the two cases using the assignment operator in the previous FAQ :

If self-assignment can be handled without any extra code, don’t add any extra code. But do add a comment so others will know that your assignment operator gracefully handles self-assignment:

Example 1a:

Example 1b:

If you need to add extra code to your assignment operator, here’s a simple and effective technique:

Or equivalently:

By the way: the goal is not to make self-assignment fast. If you don’t need to explicitly test for self-assignment, for example, if your code works correctly (even if slowly) in the case of self-assignment, then do not put an if test in your assignment operator just to make the self-assignment case fast. The reason is simple: self-assignment is almost always rare, so it merely needs to be correct - it does not need to be efficient. Adding the unnecessary if statement would make a rare case faster by adding an extra conditional-branch to the normal case, punishing the many to benefit the few.

In this case, however, you should add a comment at the top of your assignment operator indicating that the rest of the code makes self-assignment is benign, and that is why you didn’t explicitly test for it. That way future maintainers will know to make sure self-assignment stays benign, or if not, they will need to add the if test.

I’m creating a derived class; should my assignment operators call my base class’s assignment operators?

Yes (if you need to define assignment operators in the first place).

If you define your own assignment operators, the compiler will not automatically call your base class’s assignment operators for you. Unless your base class’s assignment operators themselves are broken, you should call them explicitly from your derived class’s assignment operators (again, assuming you create them in the first place).

However if you do not create your own assignment operators, the ones that the compiler create for you will automatically call your base class’s assignment operators.

Please Login to submit a recommendation.

If you don’t have an account, you can register for free.

CS253: Software Development with C++

Spring 2022, self-assignment.

Colorado State University logo

Show Lecture.Self-assignment as a slide show.

CS253 Self-assignment

check self assignment c

This illustrates the danger of self-assignment.

That is, when an object containing pointers or other handles to external resources is assigned to itself, you’ve got to be careful in operator= , or you might destroy your data before you copy it to yourself.

Copy Constructor General Outline

When a class contains a handle to external data, the copy constructor generally follows this pattern:

  • Copy the resource from the other object to this object.

That is, don’t just copy the handle (pointer, file descriptor, etc.). Instead you have to make an actual copy of the resource (copy the memory from new , create a new temporary file and copy the contents, etc.).

Of course, this is a copy constructor, not an assignment operator, so there was no previous value. We are constructing .

Assignment Operator General Outline

When a class contains a handle to external data, the assignment operator ( operator= ) generally follows this pattern:

  • Get rid of the old external data ( delete memory, close network socket, delete temporary file, unlock semaphore, etc.).
  • This is a silly class that stores a float in dynamic memory.
  • It works—so far.

Try Copy Constructor

  • That failed because the default copy ctor just copied the pointer.
  • Both objects’ dtors tried to free the same pointer … boom!
  • We deserve that, because we didn’t follow the general outline for a copy constructor. We got the default copy ctor.

Fixed Copy Constructor

  • The new copy ctor allocated more space and copied the data, not just the pointer.

Try Assignment Operator

  • The default assignment operator has the same problem.
  • Also, relying upon the compiler-created operator= when you've written the copy ctor is deprecated.

Fix Assignment Operator

  • The assignment operator now allocates space & copies the data.
  • Whaaaaaaaaaat?

Explanation

What happens inside a = a ?

  • First, delete the old data.
  • Second, copy the new data (that we just freed).
  • We must copy the data, but, sometimes, we can’t  !
  • If this is self-assignment, don’t do anything.
  • How to detect that?
  • See if the address of the left-hand-side ( this ) equals the address of the right-hand-side ( &rhs ).
  • The & in the declaration const HeapFloat &rhs means “reference to”, whereas the & in the expression   this != &rhs means ”address of”.

This Sounds Silly

  • Yeah, but, … so what? Nobody will ever really do that.
  • Not explicitly, no. But it might happen indirectly.
  • Find the smallest element.
  • Swap it with the first element.
  • What if the first element is the smallest element?
  • You’ll try to assign [0] to [0] ! Self-assignment!

Not very DRY

  • new float (*rhs.data) appears twice— WET !

The copy ctor calls operator= ; as complex objects often do. Initialize data = nullptr so the initial delete data is ok.

check self assignment c

  • Latest Articles
  • Top Articles
  • Posting/Update Guidelines
  • Article Help Forum

check self assignment c

  • View Unanswered Questions
  • View All Questions
  • View C# questions
  • View C++ questions
  • View Visual Basic questions
  • View Javascript questions
  • View Python questions
  • CodeProject.AI Server
  • All Message Boards...
  • Running a Business
  • Sales / Marketing
  • Collaboration / Beta Testing
  • Work Issues
  • Design and Architecture
  • Artificial Intelligence
  • Internet of Things
  • ATL / WTL / STL
  • Managed C++/CLI
  • Objective-C and Swift
  • System Admin
  • Hosting and Servers
  • Linux Programming
  • .NET (Core and Framework)
  • Visual Basic
  • Web Development
  • Site Bugs / Suggestions
  • Spam and Abuse Watch
  • Competitions
  • The Insider Newsletter
  • The Daily Build Newsletter
  • Newsletter archive
  • CodeProject Stuff
  • Most Valuable Professionals
  • The Lounge  
  • The CodeProject Blog
  • Where I Am: Member Photos
  • The Insider News
  • The Weird & The Wonderful
  • What is 'CodeProject'?
  • General FAQ
  • Ask a Question
  • Bugs and Suggestions

Operator to check for self assignment

check self assignment c

2 solutions

  • Most Recent

Add your solution here

Your Email  
Password  
Your Email  
?
Optional Password  
  • Read the question carefully.
  • Understand that English isn't everyone's first language so be lenient of bad spelling and grammar.
  • If a question is poorly phrased then either ask for clarification, ignore it, or edit the question and fix the problem. Insults are not welcome.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Print

Top Experts
Last 24hrsThis month
30
25
10
10
5
1,025
926
524
340
330

check self assignment c

Get the Reddit app

a subreddit for c++ questions and answers

What is the proper way to self assignment check in constructor?

In my latest learning project it has been brought to my attention that I forgot to self assignment check. However my notes are lacking on what is the best option for handling it and google has mixed views. These are the 3 scenarios I can think of. Which one is the most appropriate? Or is the best method something I have not listed here?

Eric Niebler

Judge me by my C++, not my WordPress

Post-Conditions on Self-Move

UPDATE April 8, 2016 This post has been edited since publication to reflect my evolving understanding. As a result of the issues raised in this post, it’s possible that the committee decides to strengthen the post-conditions on move, so the recommendations made here may evolve further. Stay tuned.

TL;DR: In addition to the usual rule about move operations leaving the source object in a valid but unspecified state , we can add an additional rule:

Self -move assignment should “work” and at the very least leave the object in a valid but unspecified state.

What do you think the following code should do?

Yes, it’s dumb, but with our alias-happy language, it can happen. So what does the standard say about this? For that we turn to [res.on.arguments]/p1.3 taken from the library introduction (emphasis mine):

If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument. […] If a program casts an lvalue to an xvalue while passing that lvalue to a library function (e.g. by calling the function with the argument std::move(x) ), the program is effectively asking that function to treat that lvalue as a temporary. The implementation is free to optimize away aliasing checks which might be needed if the argument was were an lvalue.

(I fixed the grammar mistake because I am a Huge Dork.) The above seems to say that std::swap(x, x) is playing with fire, because std::swap is implemented as follows:

If a and b refer to the same object, the second line of std::swap does a self-move assign. Blamo! Undefined behavior, right?

Such was what I thought when I first wrote this post until Howard Hinnant drew my attention to the requirements table for the MoveAssignable concept, which says that for the expression t = rv (emphasis mine):

If t and rv do not refer to the same object , t is equivalent to the value of rv before the assignment […] rv ’s state is unspecified. [ Note: rv must still meet the requirements of the library component that is using it, whether or not t and rv refer to the same object. […] –end note]

Ah, ha! So here we have it. After a self-move, the object is required to be in a valid-but-unspecified state.

My attention we drawn to this issue during a code review of a change I wanted to make to Folly ‘s Function class template. I wanted to change this:

The reason: let’s make moves as fast as possible and take advantage of the fact that Self-Moves Shouldn’t Happen. We assert, fix up the places that get it wrong, and make our programs an iota faster. Right?

Not so fast, said one clued-in reviewer. Self-swaps can happen quite easily in generic algorithms, and they shouldn’t trash the state of the object or the state of the program. This rang true, and so begin my investigation.

A few Google searches later turned up this StackOverflow gem from Howard Hinnant . C++ wonks know Howard Hinnant. He’s the author of libc++, and an old time C++ library developer. (Remember Metrowerks CodeWarrior ? No? Get off my lawn.) He also happens to be the person who wrote the proposal to add rvalue references to the language, so you know, Howard’s given this some thought. First Howard says this:

Some will argue that swap(x, x) is a good idea, or just a necessary evil. And this, if the swap goes to the default swap, can cause a self-move-assignment. I disagree that swap(x, x) is ever a good idea. If found in my own code, I will consider it a performance bug and fix it.

But then in an Update , he backtracks:

I’ve given this issue some more thought, and changed my position somewhat. I now believe that assignment should be tolerant of self assignment, but that the post conditions on copy assignment and move assignment are different: For copy assignment: x = y; one should have a post-condition that the value of y should not be altered. When &x == &y then this postcondition translates into: self copy assignment should have no impact on the value of x . For move assignment: x = std::move(y); one should have a post-condition that y has a valid but unspecified state. When &x == &y then this postcondition translates into: x has a valid but unspecified state. I.e. self move assignment does not have to be a no-op. But it should not crash. This post-condition is consistent with allowing swap(x, x) to just work […]

When Howard Hinnant changes his mind about something having to do with library design, I sit up and take note, because it means that something very deep and subtle is going on. In this case, it means I’ve been writing bad move assignment operators for years.

By Howard’s yardstick — and by the requirements for the MoveAssignable concept in the standard, thanks Howard! — this move assignment operator is wrong:

Move assignment operators should accept self-moves and do no evil; indeed for std::swap(f, f) to work it must .

That’s not the same as saying it needs to preserve the object’s value, though, and not preserving the object’s value can be a performance win. It can save a branch, for instance. Here is how I reformulated folly::Function ’s move assignment operator[*]:

[*] Well, not exactly, but that’s the gist.

Of note is that clear_() leaves *this in a state such that it is still OK to moveFrom_(*this) , which is what happens when that and *this are the same object. In the case of Function , it just so happens that the effect of this code is to put the Function object back into the default-constructed state, obliterating the previous value. The particular final state of the object isn’t important though, so long as it is still valid.

So, as always we have the rule about moves:

Move operations should leave the source object in a valid but unspecified state.

And to that we can add an additional rule:

Self-moves should do no evil and leave the object in a valid but unspecified state.

If you want to go further and leave the object unmodified, that’s not wrong per se , but it’s not required by the standard as it is today. Changing the value is perfectly OK (Howard and the standard say so!), and doing that might save you some cycles.

22 Replies to “Post-Conditions on Self-Move”

See also: LWG2468 ( http://cplusplus.github.io/LWG/lwg-defects.html#2468 ), LWG 2839 ( http://cplusplus.github.io/LWG/lwg-active.html#2839 ) for the “official” Library Working Group position on self-moves having defined behavior.

… which enshrines in the standard that the guideline I set out in this blog post (self-moves should leave the object in a valid but undefined state) applies to types in the Standard Library, too. Thanks, Casey.

Also, your “move assignment operators” are declared to be move constructors.

Fixed! That’s embarrassing.

Totally agree – Howard is always right, never wrong.

And when Howard corrects himself, it just means he was right, and now he is more right.

(it is very tempting to sign my name as Howard, but for once, humour doesn’t get the final say…)

I learned that self-move-assignment must leave the object in a valid state when I was burned by std::shuffle not working with objects of my type. std::shuffle in every implementation I know of can perform the equivalent of std::swap(x, x). There may be other algorithms that do the same thing. So, de facto, all decent types, including all types in the standard library implementations, already follow this rule.

Here’s one that doesn’t self-swap 🙂 : https://github.com/llvm-mirror/libcxx/blob/master/include/algorithm#L3192-L3193

Note for future readers: The algorithm linked does not avoid a self-swap. However, if we look at std::shuffle instead of the removed-from-17 std::random_shuffle , located here: https://github.com/llvm-mirror/libcxx/blob/master/include/algorithm#L3280-L3302 , we see that there is an explicit test to avoid self-swap:

if (__i != difference_type(0)) swap(*__first, *(__first + __i));

Was the reason for this explicit test that there are likely many types being used with std::shuffle or was it for performance? I’d be interested in seeing a benchmark on whether this actually helps performance. Intuitively, it seems that a larger container would benefit from this less (as there is a lower probability of any given swap being a self-swap) and thus be harmed by it more. I imagine that the worst case for this optimization would be a large array of int. Do you have such a benchmark?

The standard explicitly states that swap swaps the values referred to by a and b and doesn’t explicitly exclude those values being the same. It seems to me that the only requirement of swap is that when the operation completes a₂ == b₁ and b₂ == a₁. How swap achieves this is implementation defined but an implementation must guarantee it. My reading is that it is not undefined behaviour to call it with two values which are the same. Whether it’s a good idea or not an implementation must support it.

Taking that to be true it is an implementation of swap that binds an rvalue reference to one of it’s parameters and passes it to a member function of the other without checking that they are the same is the one invoking the undefined behaviour. Whether we like it or not the wording of the swap definition means it has to do an equality comparison to avoid invoking undefined behaviour and be standard compliant.

I saw an interesting observation on the Reddit thread for this post.

mcmcc said: “If [self move is a well-defined operation], and we view move as simply an optimization over copy, then it should assert the same post-conditions as copy.”

I recall several talks from prominent C++ community members that sold move semantics as a copy-optimization. Why shouldn’t that apply for self-move?

It’s a legitimate question. This same question is being discussed right now in relation to the Core Guidelines. Some argue for non-modifying self-move, others for valid-but-unspecified, and there are good reasons on both sides. Interestingly, the problem is not just about self-move. Any time a part is moved (or copied!) into the whole, there is potential for data loss unless the [copy/move]-and-swap idiom is used. This issue could lead to a change in the Standard, in Standard Library implementations, in the Core Guidelines, and books and articles about how to write copy/move assignment operators! I’ll write another blog post once the dust has settled.

What’s the benefit? It does preclude implementing move assignment as destruction followed by in-place construction, which is defined behavior as long as the class has no reference or const members, AFAIK.

Just to clarify: do you have an example where the proposed change would make real code work that otherwise wouldn’t?

You can always write a move-assignment operator that works and preserves the value in the case of self-move (or more generally anytime a part is moved into the whole). It comes at the cost of move-constructing a temporary and (nothrow) swapping with it. That can be expensive. The question is: is it OK to avoid making the temporary to optimize the common case if move-assign becomes mutating on self-move? The standard currently says yes, that’s OK. Some are saying no, and they have a point. Stay tuned.

I don’t buy the performance argument for a value-changing self-move assignment. Given the classic use case for move semantics (a class holding a single resource), its assignment operator would probably look something like this:

In contrast, an alias-proof value-preserving implementation could be:

All it takes is a single extra assignment.

In this case, yes, it only takes one extra assignment. As I’ve learned over the past week or so, this problem (assigning a part into the whole) comes up in many other places and in other guises, and the bulletproof solution is not always cheap. When the dust settles a bit, I hope to write a follow-up post about what we’ve learned and what we’re going to do about it.

This solution does not actually save you. If this == std::addressof(rhs) , then tmp == this->resource . When you assign from it on line 5, you are invoking implementation-defined behavior by reading from an invalid pointer. See http://eel.is/c++draft/basic.stc#4

“When the end of the duration of a region of storage is reached, the values of all pointers representing the address of any part of that region of storage become invalid pointer values. Indirection through an invalid pointer value and passing an invalid pointer value to a deallocation function have undefined behavior. Any other use of an invalid pointer value has implementation-defined behavior.”

“Some implementations might define that copying an invalid pointer value causes a system-generated runtime fault.”

Unless you are willing to accept this behavior on some platforms (which is to say, you do not support those platforms), I do not believe you can get away without a branch in the value-preserving case. Of course, this also effects your original version, as written. To be safe, your first version should look something like

delete this->resource; this->resource = nullptr; this->resource = rhs.resource; rhs.resource = nullptr;

Or, if you want to get fancy

delete std::exchange(this->resource, nullptr); this->resource = std::exchange(rhs.resource, nullptr);

If we look at the implementation of vector in some standard libraries, clang’s standard library (libc++) does the moral equivalent of this. gcc’s standard library, libstdc++, implements move assignment as constructing an empty temporary and swapping with it, then swapping with rhs , so it is also safe. At first it looks like gcc has avoided a branch, from a straightforward reading of the code, but it is still there in the destructor of the temporary. Note that both implementations have a destructive self-move (it leaves the object in the empty state).

The code Eric outlined should also be safe, assuming that his clear_ function sets the value of the pointer to something safe before it returns.

I don’t think your claim is correct. If this == &rhs, then line 3 sets this->resource to nullptr. Therefore line 4 does not invaldate tmp (it has no effect), and the assignment in line 5 still copies a valid pointer.

To me, self-swapping without alias checking is counter-intuitive. I’d expect self-swapping no-op.

Mmh. Not sure I am getting the gist here.

Motivation: Self-move may – accidentally – happen in generic algorithms. Assertion: A modifying self-move is beneficial over a fail-fast self-move.

It would seem then, that an accidental self-move introduces a silent bug by destroying information (and replacing it with a blank, almost by definition not useful data). As the resulting state is still valid, there will be no indication that anything is wrong. … This is much worse than a performance penalty, is it not? An exception or an error flag should be employed.

(On fuzzy and/or big data I could see the argument that losing the odd value would not meaningfully impact the outcome and may thus be accepted. I do not think this can be treated as the general case, though.)

Am I missing something?

It’s that generic code would accidentally self-swap. The problem is more that some generic algorithms, such as std::shuffle , need an explicit check to avoid it. If the type being passed to the algorithm can handle a self-swap, then the algorithm does not need that “extra” branch.

That being said, I do not know if any generic algorithms that do not rely on randomness have this property. I can’t think of a sorting algorithm that would cause this, for instance.

Note that a self-move-assigned container that doesn’t preserve its state would break the proposed requirement for move-assigned containers (depending on allocator) to not invalidate iterators: https://cplusplus.github.io/LWG/lwg-active.html#2321

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Notify me of follow-up comments by email.

Notify me of new posts by email.

This site uses Akismet to reduce spam. Learn how your comment data is processed .

21.12 — Overloading the assignment operator

Issues due to self-assignment

Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:

When not to handle self-assignment

The copy and swap idiom

Extra Clang Tools 19.0.0git documentation

Clang-tidy - bugprone-unhandled-self-assignment.

«   bugprone-unhandled-exception-at-new   ::   Contents   ::   bugprone-unique-ptr-array-mismatch   »

bugprone-unhandled-self-assignment ¶

cert-oop54-cpp redirects here as an alias for this check. For the CERT alias, the WarnOnlyIfThisHasSuspiciousField option is set to false .

Finds user-defined copy assignment operators which do not protect the code against self-assignment either by checking self-assignment explicitly or using the copy-and-swap or the copy-and-move method.

By default, this check searches only those classes which have any pointer or C array field to avoid false positives. In case of a pointer or a C array, it’s likely that self-copy assignment breaks the object if the copy assignment operator was not written with care.

See also: OOP54-CPP. Gracefully handle self-copy assignment

A copy assignment operator must prevent that self-copy assignment ruins the object state. A typical use case is when the class has a pointer field and the copy assignment operator first releases the pointed object and then tries to assign it:

There are two common C++ patterns to avoid this problem. The first is the self-assignment check:

The second one is the copy-and-swap method when we create a temporary copy (using the copy constructor) and then swap this temporary object with this :

There is a third pattern which is less common. Let’s call it the copy-and-move method when we create a temporary copy (using the copy constructor) and then move this temporary object into this (needs a move assignment operator):

When true , the check will warn only if the container class of the copy assignment operator has any suspicious fields (pointer or C array). This option is set to true by default.

Home Posts Topics Members FAQ

7174 The self-assignment check detects object identity, which C++ specifies as an
object's addresses.

The degenerate situation of copying a value into an object which already had
that value is less important. Just let it happen; don't always waste CPU
cycles checking for it.

--
Phlip
<-- NOT a blog!!!
Well, as long as we're dealing with hypotheticals: If (1) checking the
class for equality is cheap, (2) checking for equality frequently
evaluates to true even though it's not the same object (in the sense of
occuping the same address), and (3) using the copy constructor is very
expensive, then one can imagine using the former version, since it will
avoid unnecessary copy constructions.

The latter version ought to be the default, though.

Best regards,

Tom


That is not a declaration -- choose your words carefully.


The latter compares the ADDRESSES of two objects, while the former compares
the two objects themselves.


Yes, the former requires an accessible operator==.


Depends on a wonderous amount of factors:
(1) How the class is implemented
(2) How expensive it is to copy it
(3) How expensive it is to compare it for equality
(4) How often an object is compared to itself

If an object of the class should NEVER be assigned to itself, I would
suggest an assert:

#include <cassert>

MyClass &MyClass::opera tor=(MyClass const &rhs)
{
assert(this != &rhs);

/* Now perform assignment */

return *this;
}

--

Frederick Gotham


That is not a declaration -- choose your words carefully.



The latter compares the ADDRESSES of two objects, while the former compares
the two objects themselves.



Yes, the former requires an accessible operator==.



Depends on a wonderous amount of factors:
(1) How the class is implemented
(2) How expensive it is to copy it
(3) How expensive it is to compare it for equality
(4) How often an object is compared to itself

If an object of the class should NEVER be assigned to itself, I would
suggest an assert:

#include <cassert>

MyClass &MyClass::opera tor=(MyClass const &rhs)
{
assert(this != &rhs);

/* Now perform assignment */

return *this;
}
I think assert should not be good solution as we may not want to assert
just in case someone did it by mistake.

Here we can use shared pointers

class foo {
private:
std::tr1::share d_ptr<type_clas spt;
};

foo& foo::operator=( const foo& rhs)
{
pt.reset(new type_class(*rhs .pt)); //reset deletes the first and points
to 2nd,
//if new throws exception reset will not implement and original will
not be deleted.
return *this;
}

OR the other way

foo& foo::operator=( const foo& rhs)
{
type_class *pBefore = pt;
pt = new type_class(rhs. pt);
delete pt;
return *this;
}

These approaches are better as they are taking care of self assignment
saftey as well as exception saftey.

-SS
Well, an assert should definately not be used here but not for that
reason. Self assignment is rather common for objects when a program
gets remotely interesting. Simply not doing the assignment or devising
a way that it will just not hurt anything are the correct options.

Now, your reasoning isn't right because an assert is placed in code for
exactly that reason...in case someone accidentally violates a
pre-condition. They are there for the developer and go away in release
mode.

What you don't want is an assert that is the sole way of avoiding a
situation unless such a situation cannot be resolved, as is not the
case here. So the assert would be ok if you wanted to impose such a
restriction but the normal checks should still apply in release mode
because this could happen under conditions that where not tested and
then the program would do stupid things...and the situation is very
resolvable, you just don't do the copy.


An assert is the testing of a condition at runtime. If the condition is
true, nothing happens. If the condition is false:

(1) The program is terminated.
(2) The programmer is informed as to where they made their coding
error.

So you see, "assert" is used to catch programming errors quickly and to cut
down time on debugging.


Overkill in my opinion.
Noah Roberts posted:
If the inventor of the class deems that an object of the class should never
be assigned to itself, then an "assert" is quite appropriate. The situation
is quite akin to the following:

/* Function: CountOcc

This function counts the amount of occurrences
of a specific element in an array.

NB: (1) Neither argument may be a null pointer.
(2) The second pointer must be greater than the first.
*/

template<class T>
unsigned CountOcc(T const *pstart,T const*const pend,T const &elem)
{
assert(pstart); assert(pend); assert(pend pstart);

/* Rest of Code */
}

These asserts are very good practise in my opinion. The help the developer
without sacrificing speed of execution.

--

Frederick Gotham

If the inventor of the class deems that an object of the class should never
be assigned to itself, then an "assert" is quite appropriate. If such an inventor did indeed deem that such a pre-condition be the
case. However, that is an inappropriate precondition to enforce and
renders the class hardly usable. When designing the assignment
operator one should always be aware of, and account for (not disallow),
self-assignment. You should also try to at least provide the strong
guarantee. Both of these can often be killed with one stone simply by
accepting the parameter by value instead of by reference.

The situation The first two probably, and notice how this differs a great deal from
the self assignment problem. Namely that at least the first two
pre-conditions are totally unresolvable; there is no correct answer if
those preconditions are not met whereas the answer to self assignment
is the object itself. The last isn't even valid in that the result of
the count of any specific element in an empty array should be 0, not a
blown assert...it also guarantees nothing about the validity of that
relationship between the two addresses.

Also interesting to note is that your sticking to C constructs has
resulted in a function that is not as generic as it could be. The use
of the iterator concept instead of pointers would result in a more
useful function (it could work with any container) and remove the
necissity, and in fact the possibility, of those asserts.

The fact that asserting that a ptr != 0 in many cases is rather useless
also in that the assert can pass without a valid pointer and a 0
pointer is the easiest invalid pointer to debug. Placing the assert to
advertize the precondition is enough for it to be there though.

Why are you testing for self-assignment at all? What does the rest of
your assignment operator look like? Can you implement your operator= as
"create a temporary and swap" as in .

Gavin Deane


I would say that that depends entirely on the kind of class we're
dealing with. Let's say we have a card game, and that we have a class
called "Hand". Let's say that we code the game in such a way that a hand
should never be compared to itself -- in fact, let's say that it would be
quite perverse if it were. In such circumstances, the "assert" solves two
problems:

(1) It informs the programmer of their coding error in Debug Mode.
(2) It doesn't burdeon the valid code in Release Mode with a decrease
in speed of execution.


I believe that rule is too rigid. I don't keep many rules in mind when
programming, I like to be fluidic and open to all possibilities -- it
results in more creative code (which tends to run faster too).


If speed of execution and memory consumption are no object, then yes.
<snip code>
The first two probably, and notice how this differs a great deal from
the self assignment problem.
I believe they are very similar: They deal with something that the 3rd
party has outlawed. In the previous example, the 3rd party outlawed self-
assignment. In _this_ example, the 3rd party outlaws the passing of invalid
pointers.


Yes, but speed of execution suffers if self-assignment should trully be a
no-no. If it's extremely bizarre that an object of a certain type be
compared to itself, then we can just outlaw the practise by using an
"assert". If however it's not too weird that an object of a certain type be
compared to itself, then just go with:

if(this==&rhs)r eturn*this;


This depends on whether the 3rd party considers an empty array to be an
array.


Acknowledged, however it does guarantee that "pend" is ahead of "pstart"
(assuming of course that their comparisson doesn't invoke UB ; ) ).


I have yet to read up on iterators; can you suggest a good book? I tried
TC++PL but didn't like the way it approached the Standard Library.


Sorry I don't quite understand what you're saying in that last sentence.

--

Frederick Gotham

| last post by:
| last post by:
| last post by:
| last post by:
| last post by:
| last post by:
| last post by:
| last post by:
| last post by:

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use .

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.

  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Assignment Operators In C++

  • Move Assignment Operator in C++ 11
  • JavaScript Assignment Operators
  • Assignment Operators in Programming
  • Is assignment operator inherited?
  • Solidity - Assignment Operators
  • Augmented Assignment Operators in Python
  • bitset operator[] in C++ STL
  • C++ Assignment Operator Overloading
  • Self assignment check in assignment operator
  • Copy Constructor vs Assignment Operator in C++
  • Operators in C++
  • C++ Arithmetic Operators
  • Bitwise Operators in C++
  • Casting Operators in C++
  • Assignment Operators in C
  • Assignment Operators in Python
  • Compound assignment operators in Java
  • Arithmetic Operators in C
  • Operators in C

In C++, the assignment operator forms the backbone of many algorithms and computational processes by performing a simple operation like assigning a value to a variable. It is denoted by equal sign ( = ) and provides one of the most basic operations in any programming language that is used to assign some value to the variables in C++ or in other words, it is used to store some kind of information.

The right-hand side value will be assigned to the variable on the left-hand side. The variable and the value should be of the same data type.

The value can be a literal or another variable of the same data type.

 

Compound Assignment Operators

In C++, the assignment operator can be combined into a single operator with some other operators to perform a combination of two operations in one single statement. These operators are called Compound Assignment Operators. There are 10 compound assignment operators in C++:

  • Addition Assignment Operator ( += )
  • Subtraction Assignment Operator ( -= )
  • Multiplication Assignment Operator ( *= )
  • Division Assignment Operator ( /= )
  • Modulus Assignment Operator ( %= )
  • Bitwise AND Assignment Operator ( &= )
  • Bitwise OR Assignment Operator ( |= )
  • Bitwise XOR Assignment Operator ( ^= )
  • Left Shift Assignment Operator ( <<= )
  • Right Shift Assignment Operator ( >>= )

Lets see each of them in detail.

1. Addition Assignment Operator (+=)

In C++, the addition assignment operator (+=) combines the addition operation with the variable assignment allowing you to increment the value of variable by a specified expression in a concise and efficient way.

This above expression is equivalent to the expression:

   

2. Subtraction Assignment Operator (-=)

The subtraction assignment operator (-=) in C++ enables you to update the value of the variable by subtracting another value from it. This operator is especially useful when you need to perform subtraction and store the result back in the same variable.

   

3. Multiplication Assignment Operator (*=)

In C++, the multiplication assignment operator (*=) is used to update the value of the variable by multiplying it with another value.

 

4. Division Assignment Operator (/=)

The division assignment operator divides the variable on the left by the value on the right and assigns the result to the variable on the left.

       

5. Modulus Assignment Operator (%=)

The modulus assignment operator calculates the remainder when the variable on the left is divided by the value or variable on the right and assigns the result to the variable on the left.

     

6. Bitwise AND Assignment Operator (&=)

This operator performs a bitwise AND between the variable on the left and the value on the right and assigns the result to the variable on the left.

   

7. Bitwise OR Assignment Operator (|=)

The bitwise OR assignment operator performs a bitwise OR between the variable on the left and the value or variable on the right and assigns the result to the variable on the left.

8. Bitwise XOR Assignment Operator (^=)

The bitwise XOR assignment operator performs a bitwise XOR between the variable on the left and the value or variable on the right and assigns the result to the variable on the left.

9. Left Shift Assignment Operator (<<=)

The left shift assignment operator shifts the bits of the variable on the left to left by the number of positions specified on the right and assigns the result to the variable on the left.

10. Right Shift Assignment Operator (>>=)

The right shift assignment operator shifts the bits of the variable on the left to the right by a number of positions specified on the right and assigns the result to the variable on the left.

Also, it is important to note that all of the above operators can be overloaded for custom operations with user-defined data types to perform the operations we want.

Please Login to comment...

Similar reads.

  • Geeks Premier League 2023
  • Geeks Premier League

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

  • Windows Programming
  • UNIX/Linux Programming
  • General C++ Programming
  • self-assessment check fails

  self-assessment check fails

check self assignment c

main(){ Contact c( , 3); c.display(); cout << << endl; c.read(); c.display(); cout << ; ( i = 0; i < 1000000; i++){ Contact cp = c; c = cp; (!(i % 100000)) cout << ; } cout << endl; c.display(); system( ); 0; }
=( Contact& source) { ( == &source) { * ; } { [] _pn; ( i = 0; i < 41; i++) _name[i] = source._name[i]; _pn = PhoneNumber[source._noPN]; ( i = 0; i < source._noPN; i++) _pn[i] = source._pn[i]; * ; } }
Contact& source) { (source.isEmpty()) { setEmpty(); } { strcpy_s(_name, source._name); _name[40] = ; _pn = PhoneNumber[source._noPN]; ( i = 0; i < source._noPN; i++) _pn[i] = source._pn[i]; } }
I made a typo, sorry. What I mean't is self-assessment. In the 2nd line of the 2nd code, the condition "this == &source" always results in false. I don't understand why this condition would result in false when the values of the variables of both objects are the same.
  • Getting started with C++
  • Awesome Book
  • Awesome Community
  • Awesome Course
  • Awesome Tutorial
  • Awesome YouTube
  • Argument Dependent Name Lookup
  • Arithmitic Metaprogramming
  • Atomic Types
  • Basic input/output in c++
  • Basic Type Keywords
  • Bit Manipulation
  • Bit Operators
  • Build Systems
  • C incompatibilities
  • C++ Containers
  • C++ Debugging and Debug-prevention Tools & Techniques
  • C++ function "call by value" vs. "call by reference"
  • C++ Streams
  • C++11 Memory Model
  • Callable Objects
  • Classes/Structures
  • Client server examples
  • Common compile/linker errors (GCC)
  • Compiling and Building
  • Concurrency With OpenMP
  • Const Correctness
  • const keyword
  • Constant class member functions
  • Copy Elision
  • Copying vs Assignment
  • Curiously Recurring Template Pattern (CRTP)
  • Data Structures in C++
  • Date and time using header
  • Design pattern implementation in C++
  • Digit separators
  • Enumeration
  • Explicit type conversions
  • Expression templates
  • Floating Point Arithmetic
  • Flow Control
  • Fold Expressions
  • Friend keyword
  • Function Overloading
  • Function Template Overloading
  • Futures and Promises
  • Header Files
  • Implementation-defined behavior
  • Inline functions
  • Inline variables
  • Internationalization in C++
  • Layout of object types
  • Linkage specifications
  • Memory management
  • Metaprogramming
  • More undefined behaviors in C++
  • Move Semantics
  • mutable keyword
  • Non-Static Member Functions
  • One Definition Rule (ODR)
  • Operator Overloading
  • operator precedence
  • Optimization
  • Optimization in C++
  • Overload resolution
  • Parameter packs
  • Perfect Forwarding
  • Pimpl Idiom
  • Pointers to members
  • Polymorphism
  • Preprocessor
  • RAII: Resource Acquisition Is Initialization
  • Random number generation
  • Recursion in C++
  • Recursive Mutex
  • Refactoring Techniques
  • Regular expressions
  • Resource Management
  • Return Type Covariance
  • Returning several values from a function
  • RTTI: Run-Time Type Information
  • SFINAE (Substitution Failure Is Not An Error)
  • Side by Side Comparisons of classic C++ examples solved via C++ vs C++11 vs C++14 vs C++17
  • Singleton Design Pattern
  • Smart Pointers
  • Special Member Functions
  • Standard Library Algorithms
  • static_assert
  • std::atomics
  • std::forward_list
  • std::function: To wrap any element that is callable
  • std::integer_sequence
  • std::iomanip
  • std::optional
  • std::set and std::multiset
  • std::string
  • std::variant
  • std::vector
  • Storage class specifiers
  • Stream manipulators
  • The ISO C++ Standard
  • The Rule of Three, Five, And Zero
  • Rule of Five
  • Rule of Three
  • Rule of Zero
  • Self-assignment Protection
  • The This Pointer
  • Thread synchronization structures
  • Trailing return type
  • type deduction
  • Type Erasure
  • Type Inference
  • Type Keywords
  • Type Traits
  • Typedef and type aliases
  • Undefined Behavior
  • Unit Testing in C++
  • Unnamed types
  • Unspecified behavior
  • User-Defined Literals
  • Using declaration
  • Using std::unordered_map
  • Value and Reference Semantics
  • Value Categories
  • Variable Declaration Keywords
  • Virtual Member Functions

C++ The Rule of Three, Five, And Zero Self-assignment Protection

Fastest entity framework extensions.

When writing a copy assignment operator, it is very important that it be able to work in the event of self-assignment. That is, it has to allow this:

Self-assignment usually doesn't happen in such an obvious way. It typically happens via a circuitous route through various code systems, where the location of the assignment simply has two Person pointers or references and has no idea that they are the same object.

Any copy assignment operator you write must be able to take this into account.

The typical way to do so is to wrap all of the assignment logic in a condition like this:

Note: It is important to think about self-assignment and ensure that your code behaves correctly when it happens. However, self-assignment is a very rare occurrence and optimizing to prevent it may actually pessimize the normal case. Since the normal case is much more common, pessimizing for self-assignment may well reduce your code efficiency (so be careful using it).

As an example, the normal technique for implementing the assignment operator is the copy and swap idiom . The normal implementation of this technique does not bother to test for self-assignment (even though self-assignment is expensive because a copy is made). The reason is that pessimization of the normal case has been shown to be much more costly (as it happens more often).

Move assignment operators must also be protected against self-assignment. However, the logic for many such operators is based on std::swap , which can handle swapping from/to the same memory just fine. So if your move assignment logic is nothing more than a series of swap operations, then you do not need self-assignment protection.

If this is not the case, you must take similar measures as above.

Got any C++ Question?

pdf

  • Advertise with us
  • Cookie Policy
  • Privacy Policy

Get monthly updates about new articles, cheatsheets, and tricks.

Video Walkthrough

You will work on the assignments for CS107 on the myth machines, which you access remotely. You'll initially make a copy of the starter project to modify, use command-line tools to edit and debug your code, and use some 107-specific tools like Sanity Check and Submit to test and submit your work. See below for the common steps you'll use to work on assignments.

Logging Into Myth

You will work on your programs in CS107 remotely on the myth machines, which are pre-installed with all the necessary development tools. Check out the getting started guide for how to log in remotely.

Starting An Assignment

For each assignment, you will first "clone" a copy of the assignment starter files into your own directory so you will be able to modify files. Some assignments will have randomized or user-specific data, and each student will have their own copy of the assignment to copy. The assignments are managed using a "version control system" called git ; we will not be focusing on git in CS107, but you can feel free to look into how git works if you're interested.

Note: Do not put any CS107 assignments online publicly on GitHub or any other publicly available website . This is a violation of the Stanford Honor Code.

To clone a copy of the assignment, first navigate to the directory where you would like to store the copy of the assignment. You may wish to create a CS107 folder, for instance, in your personal AFS space, using the mkdir command. Then, use the git clone command as follows:

This will make a folder named assign0 that you can then go into to start working on the assignment. You should type the above commands exactly as shown, including the odd-looking $USER at the end, but replacing assign0 with assign1 , assign2 , etc., depending on the assignment you are cloning. Now you can start working on the assignment!

Working On The Assignment

You'll use a variety of tools to work on the assignment, such as gdb (debugger) and make (compiling), that we'll introduce this quarter.

Using Sanity Check For Testing

As part of each assignment, we provide a testing program called "sanity check" that ensures you have worked on certain required files, and compares the output of your program to that of the provided sample executable and reports on discrepancies, allowing you to detect and address any issues before you submit. It also allows you to add your own custom tests.

To run the sanity check tool for a given assignment with our provided tests, first navigate to the directory containing the assignment you would like to test. Then, execute the tools/sanitycheck command as follows:

In the output, if a test fails, it will indicate either "MISMATCH" or "NOT OK". MISMATCH indicates that your program successfully ran to completion but the output it produced did not match the output produced by the sample. NOT OK reports that your program did not successfully complete (exited due to a fatal error or timed out) and its output was not compared to the sample.

  • Passing sanity check suggests the autotester won't have problems interpreting your output, and that's good. If it doesn't match, you should fix your output to meet the required format so that your output is not misjudged in grading. To earn proper credit, your program must conform to the output specification given in the assignment writeup and match the behavior of our sample executable. Minor variations like different amounts of whitespace can usually be ignored, but changing the format, reordering output, or leaving behind extraneous print debugging statements will thwart the autotester and cause your program to be marked wrong. If sanitycheck fails when you run it on the final version you submit, you will lose points when we re-run that test when we grade the assignment. Just because sanitycheck passes does not mean that your assignment is correct, but failing a test means that it is not correct.
  • There are a few situations, such as allowed latitude in the spec or equivalent re-wording of error messages, where a mismatch is not actually an error--- i.e. the program's behavior is a valid alternative to the sample, but sanity check doesn't know that. The autotester defers these cases to the judgment of the grading CA to identify whether such mismatches are true failures or harmless variation.
  • You can run sanity check as many times as you need. Our submit tool will even encourage one final run before you submit.
  • An additional benefit of running sanitycheck early and often is that it makes a snapshot of your code as a safety precaution. This backup replaces the original starter code generated for you, so you can re-clone the assignment using the same git clone command and get the last code you backed up.

Using Sanity Check With Your Own Custom Tests

The default tests supplied for sanity check may not be particularly rigorous nor comprehensive, so you will want to supplement with additional tests. You can create inputs of your own and write them into custom tests to be used by the sanitycheck tool. Create a text file using this format:

To run your custom tests, invoke sanitycheck with its optional argument, which is the name of the custom test file

When invoked with an argument, sanity check will use the test cases from the named file instead of the standard ones. For each custom test listed in the file, sanity check runs the sample solution with the given command-line arguments and captures its output, then runs your program with the same arguments to capture its output, and finally compares the two results and reports any mismatches.

Submitting An Assignment

Once you've finished working on an assignment, it's time to submit! The tools/submit command lets you submit your work right from myth . The submit tool verifies your project's readiness for submission. It will make the project to ensure there is no build failure and will offer you the option to run sanity check. If any part of verification fails, the submission is rejected and you must fix the issues and try submit again. Here's an example of using this command.

  • If verification passes and submissions are being accepted, the project is submitted and a confirmation message indicates success. If the deadline has passed and grace period expired, the submission is rejected.
  • To submit an updated version, just repeat the same steps. Only your most recent submission is graded.
  • submitting performs the same backup process as sanity check.
  • If you run into a submit failure that you cannot resolve, please seek help from the course staff. We recommend that you make a test submit well in advance of the deadline to confirm things will roll smoothly when the time comes.

Submission deadlines are firm. Cutting it too close runs the risk of landing on the wrong side -- don't let this happen to you! Submit early to give yourself a safety cushion and avoid the last-minute stress.

Assignment Tips

Be cautious with C: C is designed for high efficiency and unrestricted programmer control, with no emphasis on safety and little support for high-level abstractions. A C compiler won't complain about such things as uninitialized variables, narrowing conversions, or functions that fail to return a needed value. C has no runtime error support, which means no helpful messages when your code accesses an array out of bounds or dereferences an invalid pointer; such errors compile and execute with surprising results. Keep an eye out for problems that you may have previously depended on the language to detect for you.

Memory and pointers: Bugs related to memory and/or pointers can be tricky to resolve. Make sure you understand every part of your code that you write or change. Also keep in mind that the observable effects of a memory error can come at a place and time far removed from the root cause (i.e. running off the end of a array may "work fine" until you later read the contents of a supposedly unrelated variable). gdb and Valgrind can be extremely helpful in resolving these kinds of bugs. In particular, Valgrind is useful throughout the programming process, not just at the end. Valgrind reports on two types of memory issues: errors and leaks. Memory errors are toxic and should be found and fixed without delay. Memory leaks are of less concern and can be ignored early in development. Given that the wrong deallocation can wreak havoc, we recommend you write the initial code with all free() calls commented out. Much later, after having finished with the correct functionality and turning your attention to polishing, add in the free calls one at a time, run under Valgrind, and iterate until you verify complete and proper deallocation.

Use good style from the start : Always start with good decomposition, rather than adding it later. Sketch each function's role and have a rough idea of its inputs and outputs. A function should be designed to complete one well-defined task. If you can't describe the function's role in a sentence or two then maybe your function is doing too much and should be decomposed further. Commenting the function before you write the code may help you clarify your design (what the function does, what inputs it takes, and what outputs it produces, how it will be used). Start by using good variable names, rather than going through and changing them later. Using good style the first time makes your code better designed, easier to understand, and easier to debug.

Understand your code : At every step, you want to ensure that you understand the code you are writing, what it does, and how it works. Don't make changes without understanding why you are making them, and what the result will be.

Test : use our recommended testing techniques to incrementally develop your program, test at each step, and always have a working program.

Get help if you need it! : 107 has a lot of helpful resources, including written materials on the web site, textbook readings, lectures, labs, the online discussion forum, helper hours, and more. We are happy to help or answer your questions!

Frequently Asked Questions

How can i reproduce/debug a problem that appears during sanity check.

Look through the sanity check output to find the command being executed:

Run that same command (in shell, gdb, or Valgrind) to replicate the situation being tested. You can also view the file contents (such as the hymn file in the above command) to better understand what is being tested.

Is it possible to write a custom test to verify Valgrind correctness or memory/time efficiency?

Unfortunately not; custom sanity check tests compare on output only. You will need to supplement with other forms of testing to verify those additional requirements.

Can I submit a program that doesn't pass sanity check?

We strongly recommend that you resolve any sanity check failures before submitting, but the submit tool will not force you to do so. To submit a project doesn't pass sanity check, respond no when asked if you want to run sanity check, and the project will be submitted without that check.

How can I verify that my submission was successful?

Your gradebook page (accessible from the navigation bar at the top) lists the timestamp of the most recent submission we have received.

Although it is not necessary, if you would like to triple-check, you can view the contents of your submission by re-cloning your class repo. For example, navigate to your home directory and git clone /afs/ir/class/cs107/repos/assignN/$USER mysubmission . This will create a mysubmission directory that contains the files you submitted for assignN (be sure to replace N with the assignment number). If you're satisfied that everything is as intended in mysubmission , then you're done and you can delete the mysubmission directory. If not, figure out what's not right, fix it, and submit again.

  • Stack Overflow Public questions & answers
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Talent Build your employer brand
  • Advertising Reach developers & technologists worldwide
  • Labs The future of collective knowledge sharing
  • About the company

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Is a self-assignment check really required while implementing move assignment operator for a class? [duplicate]

//since it will be called on r-value so why self-assignment ??

  • move-semantics
  • move-assignment-operator

einpoklum's user avatar

  • 1 Type a; a = std::move(a); Technically, it's not required at all anytime, though can be very helpful in Rule-of-[35]-subject classes, to get consistency for a small price. –  bipll Commented Dec 2, 2018 at 10:37
  • With the code snippet from bipll you can figure it out yourself. Write a small class that manages an int* and implement move assignment for it without checking for self-assignment. How bug-free is it? –  StoryTeller - Unslander Monica Commented Dec 2, 2018 at 11:12
  • If we write a class that has copy assignment operator and move assignment operator . so self assignment check in one (copy or move) operator is enough . rather than checking in both (copy and move) . –  Hamza Commented Dec 2, 2018 at 12:39
  • For the stl, self move assignment is unspecified. See this answer (by a top c++ committee member, and implementer of libc++) –  Oliv Commented Dec 2, 2018 at 12:41
  • My opinion is to do as in the STL. But you can make an assert: assert(this!=&rhs) and see what happens. Otherwise you can specify it has a default semantic, like resetting the object. –  Oliv Commented Dec 2, 2018 at 12:43

Suppose your class holds a pointer to some buffer that it allocates. Now, in a naive move-assignment operator, you would:

  • Free your own buffer
  • Assign the other object's buffer pointer to your buffer pointer
  • Assign null to the other object's buffer pointer, and perhaps set its size to 0

This will not make you dereference a null pointer, but - you've just lost all data in your buffer, which is likely not what you wanted, nor what the user expected.

... but not always

There is a (narrow) exception to the rule above: The case of your move-assignment operator being 'idempotent' for self-assignment. For example, if your assignment operator only involves assignment of the members - then it's safe to self-assign just like a regular assignment (trusting that the members' self-assignment implementations are valid). Nothing will be changed or lost.

This exception to the rule is indeed narrow, since the above is mostly true for the example I gave - in which case you would use the default move-assignment operator. Still, just because you don't find this check in someone's code does not mean there's a bug.

  • 2 "you've just lost all data in your buffer." Which is usually not a bad thing (do you have any case, where this is actually a problem?). The standard doesn't say that the data must be kept: eel.is/c++draft/utility.arg.requirements#tab:moveassignable . And indeed, for example, moving std::vector to itself will remove its content (both libc++ and stdlibc++). –  geza Commented Dec 2, 2018 at 12:21
  • @geza: Always. after assigning y to x you expect x to have the same value as y had before (move or no move). –  einpoklum Commented Dec 2, 2018 at 12:31
  • On the other hand, as you moved from y , it is not unexpected that its content is empty. So there are contradicting expectations in this case. That's why I ask, where does this mean actually a problem?. For example, "moving" swap still works ( tmp = move(a); a = move(b); b = move(tmp) ). Is there any algorithm, where this behavior (data-loss) causes a problem? It must have a reason that the standard doesn't require data be kept in this case. –  geza Commented Dec 2, 2018 at 12:43
  • @geza Interesting reference: stackoverflow.com/a/9322542/5632316 –  Oliv Commented Dec 2, 2018 at 12:51
  • @Oliv: He says: "For move assignment: x = std::move(y); one should have a post-condition that y has a valid but unspecified state." But there is another reasonable post-condition: x should be equal to what y was before the assignment. And it is violated. Which usually doesn't cause any problems (I haven't found any case yet). But it still can be unexpected. –  geza Commented Dec 2, 2018 at 13:12

Not the answer you're looking for? Browse other questions tagged c++ c++11 move-semantics move-assignment-operator or ask your own question .

  • Featured on Meta
  • Upcoming sign-up experiments related to tags
  • The return of Staging Ground to Stack Overflow
  • Policy: Generative AI (e.g., ChatGPT) is banned

Hot Network Questions

  • When should a function be given an argument vs getting the data itself?
  • What was the submarine in the film "Ice Station Zebra"?
  • How does MPPT maintain a constant voltage?
  • Tiny book about a planet full of man-eating sunflowers
  • Stability of an ideal Differentiator with a "classical" Op Amp vs using a transimpedance amplifier
  • Is there a category even more general than "thing"?
  • Episode of a sci-fi series about a salesman who loses the ability to understand English
  • Mechanistic view of the universe
  • Where did the pronunciation of the word "kilometer/kilometre" as "kl OM iter" rather than "KILL o meeter" originate?
  • Is zip tie a durable way to carry a spare tube on a frame?
  • Would it be possible for a living being the size of a planet to survive?
  • A Colorful explosion
  • Should I attach my deck to the house?
  • Personal Loan to a Friend
  • if people are bred like dogs, what can be achieved?
  • Who is a "sibling"?
  • Finding reflexive, transitive closure
  • What is the meaning of "Attempt any air"?
  • Freewheeling diode in a capacitor
  • How to tell if the item language is the fallback language or the regular language version
  • Correct my understanding of Digital Signature Algorithm for TLS certificates?
  • How to make Region from Spline curve
  • Were there 3D accelerators built on discrete logic?
  • How to repair a "pull" shut-off valve for the toilet?

check self assignment c

IMAGES

  1. Self Check Assignment

    check self assignment c

  2. Assignment Operators in C

    check self assignment c

  3. Assignment Operators in C++

    check self assignment c

  4. Assignment Operators in C with Examples

    check self assignment c

  5. Assignment Operators in C

    check self assignment c

  6. Assignment Operators in C++

    check self assignment c

VIDEO

  1. Augmented assignment operators in C

  2. 25 March 2024

  3. C PROGRAMMING

  4. INORGANIC ASSIGNMENT C BY SHASHI SIR (9810657809)

  5. INORGANIC ASSIGNMENT C BY SHASHI SIR (9810657809)

  6. INORGANIC ASSIGNMENT C BY SHASHI SIR (9810657809)

COMMENTS

  1. c++

    Example 2: A copy assignment operator that is written in such a way that it must check for self-assignment is probably not strongly exception-safe either. What does he mean by the term "check for self-assignment"? [INQUIRY] Dave and AndreyT shows us exactly what "check for self-assignment" means. That's good. But the question is not over.

  2. Self assignment check in assignment operator

    If we have an object say a1 of type Array and if we have a line like a1 = a1 somewhere, the program results in unpredictable behavior because there is no self assignment check in the above code. To avoid the above issue, self assignment check must be there while overloading assignment operator. For example, following code does self assignment check.

  3. Assignment Operators

    If self-assignment can be handled without any extra code, don't add any extra code. But do add a comment so others will know that your assignment operator gracefully handles self-assignment: Example 1a: Fred& Fred::operator= (const Fred& f) {. // This gracefully handles self assignment. *p_ = *f.p_; return *this;

  4. CS253

    Assignment Operator General Outline. When a class contains a handle to external data, the assignment operator ( operator=) generally follows this pattern: Get rid of the old external data ( delete memory, close network socket, delete temporary file, unlock semaphore, etc.). Copy the resource from the other object to this object.

  5. The assignment operator

    The steps in writing our own assignment operator are the following: Check for self-assignment. Delete old memory. Allocate new memory. Copy the data. Return *this. Notice the worry about self-assignment, as in "A = A". We need to check for this both to avoid unnecessary work and to avoid problems later when we delete the old memory.

  6. When should we write our own assignment operator in C++?

    In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions

  7. [Solved] Operator to check for self assignment

    I made a simple class with a int pointer created using new. i handled the assignment operator checking for self assignment and deleting the original object. after asking some questions it turns out in my example both checking for self assignment was unnecessary and deleting was unnecessary which i thought i needed to do. otherwise the pointer would move and id lose the ability to delete that ...

  8. What is the proper way to self assignment check in constructor?

    The first approach is more standard so if you see the second in practice it is likely a good developer will question if this is self-assignment safe or not. If you had a different structure: struct Foo {. std::shared_ptr<Bar> m_p; }; That would also be self-assignment safe if you just use m_p = src.m_p; .

  9. c++

    I have always seen the recommendation that the check is done explicitly. You've been looking in the wrong places, see e.g. C++ Coding Standards by Sutter & Alexandrescu. Self-assignment is exceedingly rare in most programs, so an explicit check adds a small cost to every self-assignment even though the check is almost always false.

  10. Post-Conditions on Self-Move

    For move assignment: 1. x = std::move(y); one should have a post-condition that y has a valid but unspecified state. When &x == &y then this postcondition translates into: x has a valid but unspecified state. I.e. self move assignment does not have to be a no-op. But it should not crash.

  11. 21.12

    When not to handle self-assignment. Typically the self-assignment check is skipped for copy constructors. Because the object being copy constructed is newly created, the only case where the newly created object can be equal to the object being copied is when you try to initialize a newly defined object with itself: someClass c { c };

  12. bugprone-unhandled-self-assignment

    By default, this check searches only those classes which have any pointer or C array field to avoid false positives. In case of a pointer or a C array, it's likely that self-copy assignment breaks the object if the copy assignment operator was not written with care. See also: OOP54-CPP. Gracefully handle self-copy assignment

  13. Assignment operator self-assignment check

    The self-assignment check detects object identity, which C++ specifies as an. object's addresses. The degenerate situation of copying a value into an object which already had. that value is less important. Just let it happen; don't always waste CPU.

  14. Copy Constructor vs Assignment Operator in C++

    In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions

  15. Assignment Operators In C++

    In C++, assignment operator should be overloaded with self assignment check. For example, consider the following class Array and overloaded assignment operator function without self assignment check. // A sample class class Array { private: int *ptr; int size; public: Array& operator = (const Array &rhs); // constructors and other functions

  16. self-assessment check fails

    I have an overloaded assignment operator function. Within the function I have a self-assessment check that does not seem to work as expected. I've spent the whole day trying to figure out what the problem is. I am able to successfully get the self-assessment check to work properly when I write a entirely new code on my own but I am not able to ...

  17. C++ Tutorial => Self-assignment Protection

    c++11. Move assignment operators must also be protected against self-assignment. However, the logic for many such operators is based on std::swap, which can handle swapping from/to the same memory just fine. So if your move assignment logic is nothing more than a series of swap operations, then you do not need self-assignment protection.

  18. c++

    Usually, when overloading and assign operator, one should check for self-assignment. In a simple non-templated class it would like the following: MyClass& MyClass::operator=(const MyClass&...

  19. CS107 Working On Assignments

    To run the sanity check tool for a given assignment with our provided tests, first navigate to the directory containing the assignment you would like to test. ... Assignment Tips. Be cautious with C: C is designed for high efficiency and unrestricted programmer control, with no emphasis on safety and little support for high-level abstractions ...

  20. c++

    There is a (narrow) exception to the rule above: The case of your move-assignment operator being 'idempotent' for self-assignment. For example, if your assignment operator only involves assignment of the members - then it's safe to self-assign just like a regular assignment (trusting that the members' self-assignment implementations are valid).