21.12 — Overloading the assignment operator

01 Career Opportunities

02 beginner, 03 intermediate, 04 advanced, 05 training programs, c programming assignment operators, free c programming online course with certificate, what is an assignment operator in c, types of assignment operators in c.

1. Simple Assignment Operator (=)

Example of simple assignment operator.

2. Compound Assignment Operators

+=addition assignmentIt adds the right operand to the left operand and assigns the result to the left operand.
-=subtraction assignmentIt subtracts the right operand from the left operand and assigns the result to the left operand.
*=multiplication assignmentIt multiplies the right operand with the left operand and assigns the result to the left operand
/=division assignmentIt divides the left operand with the right operand and assigns the result to the left operand.
%=modulo assignmentIt takes modulus using two operands and assigns the result to the left operand.

Example of Augmented Arithmetic and Assignment Operators

&=bitwise AND assignmentIt performs the bitwise AND operation on the variable with the value on the right
|=bitwise OR assignmentIt performs the bitwise OR operation on the variable with the value on the right
^=bitwise XOR assignmentIt performs the bitwise XOR operation on the variable with the value on the right
<<=bitwise left shift assignmentShifts the bits of the variable to the left by the value on the right
>>=bitwise right shift assignmentShifts the bits of the variable to the right by the value on the right

Example of Augmented Bitwise and Assignment Operators

Practice problems on assignment operators in c, 1. what will the value of "x" be after the execution of the following code, 2. after executing the following code, what is the value of the number variable, benefits of using assignment operators, best practices and tips for using the assignment operator, live classes schedule.

Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast
Filling Fast

About Author

Home » Learn C Programming from Scratch » C Assignment Operators

C Assignment Operators

Summary : in this tutorial, you’ll learn about the C assignment operators and how to use them effectively.

Introduction to the C assignment operators

An assignment operator assigns the vale of the right-hand operand to the left-hand operand. The following example uses the assignment operator (=) to assign 1 to the counter variable:

After the assignmment, the counter variable holds the number 1.

The following example adds 1 to the counter and assign the result to the counter:

The = assignment operator is called a simple assignment operator. It assigns the value of the left operand to the right operand.

Besides the simple assignment operator, C supports compound assignment operators. A compound assignment operator performs the operation specified by the additional operator and then assigns the result to the left operand.

The following example uses a compound-assignment operator (+=):

The expression:

is equivalent to the following expression:

The following table illustrates the compound-assignment operators in C:

OperatorOperation PerformedExampleEquivalent expression
Multiplication assignmentx *= yx = x * y
Division assignmentx /= yx = x / y
Remainder assignmentx %= yx = x % y
Addition assignmentx += yx = x + y
Subtraction assignmentx -= yx = x – y
Left-shift assignmentx <<= yx = x <<=y
Right-shift assignmentx >>=yx = x >>= y
Bitwise-AND assignmentx &= yx = x & y
Bitwise-exclusive-OR assignmentx ^= yx = x ^ y
Bitwise-inclusive-OR assignmentx |= yx = x | y
  • A simple assignment operator assigns the value of the left operand to the right operand.
  • A compound assignment operator performs the operation specified by the additional operator and then assigns the result to the left operand.

CProgramming Tutorial

  • C Programming Tutorial
  • Basics of C
  • C - Overview
  • C - Features
  • C - History
  • C - Environment Setup
  • C - Program Structure
  • C - Hello World
  • C - Compilation Process
  • C - Comments
  • C - Keywords
  • C - Identifiers
  • C - User Input
  • C - Basic Syntax
  • C - Data Types
  • C - Variables
  • C - Integer Promotions
  • C - Type Conversion
  • C - Type Casting
  • C - Booleans
  • Constants and Literals in C
  • C - Constants
  • C - Literals
  • C - Escape sequences
  • C - Format Specifiers
  • Operators in C
  • C - Operators
  • C - Arithmetic Operators
  • C - Relational Operators
  • C - Logical Operators
  • C - Bitwise Operators
  • C - Assignment Operators
  • C - Unary Operators
  • C - Increment and Decrement Operators
  • C - Ternary Operator
  • C - sizeof Operator
  • C - Operator Precedence
  • C - Misc Operators
  • Decision Making in C
  • C - Decision Making
  • C - if statement
  • C - if...else statement
  • C - nested if statements
  • C - switch statement
  • C - nested switch statements
  • C - While loop
  • C - For loop
  • C - Do...while loop
  • C - Nested loop
  • C - Infinite loop
  • C - Break Statement
  • C - Continue Statement
  • C - goto Statement
  • Functions in C
  • C - Functions
  • C - Main Function
  • C - Function call by Value
  • C - Function call by reference
  • C - Nested Functions
  • C - Variadic Functions
  • C - User-Defined Functions
  • C - Callback Function
  • C - Return Statement
  • C - Recursion
  • Scope Rules in C
  • C - Scope Rules
  • C - Static Variables
  • C - Global Variables
  • Arrays in C
  • C - Properties of Array
  • C - Multi-Dimensional Arrays
  • C - Passing Arrays to Function
  • C - Return Array from Function
  • C - Variable Length Arrays
  • Pointers in C
  • C - Pointers
  • C - Pointers and Arrays
  • C - Applications of Pointers
  • C - Pointer Arithmetics
  • C - Array of Pointers
  • C - Pointer to Pointer
  • C - Passing Pointers to Functions
  • C - Return Pointer from Functions
  • C - Function Pointers
  • C - Pointer to an Array
  • C - Pointers to Structures
  • C - Chain of Pointers
  • C - Pointer vs Array
  • C - Character Pointers and Functions
  • C - NULL Pointer
  • C - void Pointer
  • C - Dangling Pointers
  • C - Dereference Pointer
  • C - Near, Far and Huge Pointers
  • C - Initialization of Pointer Arrays
  • C - Pointers vs. Multi-dimensional Arrays
  • Strings in C
  • C - Strings
  • C - Array of Strings
  • C - Special Characters
  • C Structures and Unions
  • C - Structures
  • C - Structures and Functions
  • C - Arrays of Structures
  • C - Self-Referential Structures
  • C - Lookup Tables
  • C - Dot (.) Operator
  • C - Enumeration (or enum)
  • C - Structure Padding and Packing
  • C - Nested Structures
  • C - Anonymous Structure and Union
  • C - Bit Fields
  • C - Typedef
  • File Handling in C
  • C - Input & Output
  • C - File I/O (File Handling)
  • C Preprocessors
  • C - Preprocessors
  • C - Pragmas
  • C - Preprocessor Operators
  • C - Header Files
  • Memory Management in C
  • C - Memory Management
  • C - Memory Address
  • C - Storage Classes
  • Miscellaneous Topics
  • C - Error Handling
  • C - Variable Arguments
  • C - Command Execution
  • C - Math Functions
  • C - Static Keyword
  • C - Random Number Generation
  • C - Command Line Arguments
  • C Programming Resources
  • C - Questions & Answers
  • C - Quick Guide
  • C - Cheat Sheet
  • C - Useful Resources
  • C - Discussion
  • Selected Reading
  • UPSC IAS Exams Notes
  • Developer's Best Practices
  • Questions and Answers
  • Effective Resume Writing
  • HR Interview Questions
  • Computer Glossary

Assignment Operators in C

In C language, the assignment operator stores a certain value in an already declared variable. A variable in C can be assigned the value in the form of a literal, another variable, or an expression.

The value to be assigned forms the right-hand operand, whereas the variable to be assigned should be the operand to the left of the " = " symbol, which is defined as a simple assignment operator in C.

In addition, C has several augmented assignment operators.

The following table lists the assignment operators supported by the C language −

Operator Description Example
= Simple assignment operator. Assigns values from right side operands to left side operand C = A + B will assign the value of A + B to C
+= Add AND assignment operator. It adds the right operand to the left operand and assign the result to the left operand. C += A is equivalent to C = C + A
-= Subtract AND assignment operator. It subtracts the right operand from the left operand and assigns the result to the left operand. C -= A is equivalent to C = C - A
*= Multiply AND assignment operator. It multiplies the right operand with the left operand and assigns the result to the left operand. C *= A is equivalent to C = C * A
/= Divide AND assignment operator. It divides the left operand with the right operand and assigns the result to the left operand. C /= A is equivalent to C = C / A
%= Modulus AND assignment operator. It takes modulus using two operands and assigns the result to the left operand. C %= A is equivalent to C = C % A
<<= Left shift AND assignment operator. C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator. C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator. C &= 2 is same as C = C & 2
^= Bitwise exclusive OR and assignment operator. C ^= 2 is same as C = C ^ 2
|= Bitwise inclusive OR and assignment operator. C |= 2 is same as C = C | 2

Simple Assignment Operator (=)

The = operator is one of the most frequently used operators in C. As per the ANSI C standard, all the variables must be declared in the beginning. Variable declaration after the first processing statement is not allowed.

You can declare a variable to be assigned a value later in the code, or you can initialize it at the time of declaration.

You can use a literal, another variable, or an expression in the assignment statement.

Once a variable of a certain type is declared, it cannot be assigned a value of any other type. In such a case the C compiler reports a type mismatch error.

In C, the expressions that refer to a memory location are called "lvalue" expressions. A lvalue may appear as either the left-hand or right-hand side of an assignment.

On the other hand, the term rvalue refers to a data value that is stored at some address in memory. A rvalue is an expression that cannot have a value assigned to it which means an rvalue may appear on the right-hand side but not on the left-hand side of an assignment.

Variables are lvalues and so they may appear on the left-hand side of an assignment. Numeric literals are rvalues and so they may not be assigned and cannot appear on the left-hand side. Take a look at the following valid and invalid statements −

Augmented Assignment Operators

In addition to the = operator, C allows you to combine arithmetic and bitwise operators with the = symbol to form augmented or compound assignment operator. The augmented operators offer a convenient shortcut for combining arithmetic or bitwise operation with assignment.

For example, the expression "a += b" has the same effect of performing "a + b" first and then assigning the result back to the variable "a".

Run the code and check its output −

Similarly, the expression "a <<= b" has the same effect of performing "a << b" first and then assigning the result back to the variable "a".

Here is a C program that demonstrates the use of assignment operators in C −

When you compile and execute the above program, it will produce the following result −

  • Operating Systems & Software
  • Programmer's Symposium

[C++] Why can't I externally overload operator= with my class on the RHS?

  • Thread starter .mobius
  • Start date Jun 25, 2003

More options

Ars scholae palatinae.

  • Jun 25, 2003
  • Add bookmark

I'm writing a wrapped data class to allow me to easily convert between several similar datatypes. That is, I have a class MyClass which internally represents an item, but can interact with ints, floats, doubles, all in predefined ways. This is a consummate example of why operator overloading is a Good Thing, right? I can write:<BR><pre class="ip-ubbcode-code-pre"> resultInt = anInt + MyInstance; resultFloat = aFloat + MyInstance; </pre><BR>and it all works transparently to the user of the class. <B>But</B>, I can't do what I want with assignment. For example:<BR><pre class="ip-ubbcode-code-pre"> myInt = myInstance; // All good and happy and right. myInstance = myInt; // Apparently not allowed. (Why not?). </pre><BR><BR>To do the second, one would naturally define <pre class="ip-ubbcode-code-pre">operator= (int lhs, const MyClass& rhs);</pre> externally and include it as a friend of MyClass. However, it seems this is not allowed (at least, according to VC++ 6 docs; I haven't tried GCC yet).<BR><BR>Why is this not allowed? How should I handle it instead? I'm at a loss, because I can't think of any other natural way to write this, and I can't find any info online about how to make it work.<BR><BR>Thanks!<BR><BR><BR>(.mobius)<BR><BR>[This message was edited by .mobius on June 25, 2003 at 15:13.]  

Well, not being a language lawyer, I can't say much here, though perhaps this somehow conflicts with the copy constructor?<BR><BR>OT: In doing some googling on this, I did come across an interesting paper by Stroustrup on generalized overloading... PDF  

Ars Centurion

Try adding a cast operator to your class...<BR><BR>Like:<BR><BR><pre class="ip-ubbcode-code-pre"> #include <iostream> using namespace std; class MyInt { public: MyInt(int a) : _a(a) { } operator int() { return _a; } private: int _a; }; int main(int argc, char* argv[]) { MyInt a(7); cout << (int) a << endl; return 0; } </pre>  

The problem isn't that I specifically am having an issue making it work correctly. The problem is that it is illegal in C++ to have an external operator definition for =, according to VC++ docs.<BR><BR>I'm curious as to why they made this illegal, since it would seem to be a useful thing to be able to do, and how to get around it, because I can't imagine I'm the first person to look at this and think "it sure would be nice if I could overload my = operator so that I can set some primitive type equal to my class"--more importantly, I'm certainly not the most ingenious or experienced C++ programmer to come across this.<BR><BR>EDIT: Hyper165, you posted while I was replying.<BR><BR>That's interesting. Do I need to have MyInt::int() defined as a public method for that to work?<BR>I'll try it out. It seems to be what I want, but it seems like an odd way to do it.<BR><BR>Thanks!<BR><BR>EDIT again:<BR>I misread that. You're overloading the (int) casting operator. That makes a whole lot more sense now.<BR><BR>[This message was edited by .mobius on June 25, 2003 at 15:59.]  

Perhaps I misunderstood your question, but I don't quite see how that code helps with<BR><BR><pre class="ip-ubbcode-code-pre"> myInstance = myInt; // Apparently not allowed. (Why not?). </pre><BR><BR>Assuming that myInstance is your class, and myInt is just a regular int.<BR><BR>Of course, if you're happy wrapping your ints in a MyInt class, then it's fine... but then, wouldn't the = overloading work, just done in the MyInt class?<BR><BR>Maybe I got something backwards.  

Ahh, I think I finally figured out what you were asking.<BR><BR>Constructors, destructors and assignment (pure and op=) must be member functions.<BR><BR>You certainly should be able to do this:<BR><BR><pre class="ip-ubbcode-code-pre"> class A { public: A() {...} A(int a) {...} A(const A&a) {...} operator=(int a) {...} operator=(const A& a) {...} }; int main() { A a1; A a2 = a1; A a3(a1); A a4; a4 = a1; A a5(1); A a6; a6 = 10; } </pre><BR><BR>However, you cannot do this :<BR><BR><pre class="ip-ubbcode-code-pre"> class B { } operator = (B& lhs, int rhs) {...} operator += (B& lhs, const B& rhs) {...} //etc </pre>  

Tristram got what I was asking. What I meant was that I can't do<pre class="ip-ubbcode-code-pre">any_old_int = MyInstance;</pre> by creating a free function overloaded operator signed thus:<pre class="ip-ubbcode-code-pre">int operator=(int lhs, const MyClass& rhs);</pre><BR>I got that backwards in my first post.<BR><BR>Hyper165's solution is good, though; it lets me do <pre class="ip-ubbcode-code-pre">any_old_int = (int) MyInstance;</pre><BR>That's really just as good.<BR><BR>I still wonder why operator= can't be a free function, and has to be a member method.  

Not sure why, exactly, but probably because it modifes the lvalue in place, not replacing it with a copy.<BR><BR>I am pretty sure that Koenig's <I>Inside the C++ Object Model</I> talks about this, but I don't have my copy atm.  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by .mobius:<BR>Tristram got what I was asking. What I meant was that I can't do<pre class="ip-ubbcode-code-pre">any_old_int = MyInstance;</pre> by creating a free function overloaded operator signed thus:<pre class="ip-ubbcode-code-pre">int operator=(int lhs, const MyClass& rhs);</pre><BR>I got that backwards in my first post.<BR><HR></BLOCKQUOTE><BR><BR>Wouldn't the signature need to be something more like<pre class="ip-ubbcode-code-pre"> int operator=(int &lhs, const MyClass& rhs); </pre><BR><BR>Since the = operator returns the value it assigned to the lhs, but also directly does the assigning, and thus needs a reference to the lvalue so it can be rewritten?  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by QuantumET:<BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by .mobius:<BR>Tristram got what I was asking. What I meant was that I can't do<pre class="ip-ubbcode-code-pre">any_old_int = MyInstance;</pre> by creating a free function overloaded operator signed thus:<pre class="ip-ubbcode-code-pre">int operator=(int lhs, const MyClass& rhs);</pre><BR>I got that backwards in my first post.<BR><HR></BLOCKQUOTE><BR><BR>Wouldn't the signature need to be something more like<pre class="ip-ubbcode-code-pre"> int operator=(int &lhs, const MyClass& rhs); </pre><BR><BR>Since the = operator returns the value it assigned to the lhs, but also directly does the assigning, and thus needs a reference to the lvalue so it can be rewritten?<HR></BLOCKQUOTE><BR><BR>Mmm. Yes, you're right. However, the entire external operator is disallowed completely, so it's sort of moot.  

<blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by .mobius:<br><blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by QuantumET:<br><blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by .mobius:<br>Tristram got what I was asking. What I meant was that I can't do<pre class="ip-ubbcode-code-pre">any_old_int = MyInstance;</pre> by creating a free function overloaded operator signed thus:<pre class="ip-ubbcode-code-pre">int operator=(int lhs, const MyClass& rhs);</pre> <br>I got that backwards in my first post.<br><hr> </blockquote> <br><br>Wouldn't the signature need to be something more like<pre class="ip-ubbcode-code-pre"> int operator=(int &lhs, const MyClass& rhs); </pre> <br><br>Since the = operator returns the value it assigned to the lhs, but also directly does the assigning, and thus needs a reference to the lvalue so it can be rewritten?<hr> </blockquote> <br><br>Mmm. Yes, you're right. However, the entire external operator is disallowed completely, so it's sort of moot.<hr> </blockquote> <br><br>Well, yes, but that doesn't mean your imaginary declarations shouldn't be correct. -- View image here: http://arstechnica.infopop.net/infopop/emoticons/icon_wink.gif --<br><br>Perhaps there's a performance issue... if you could overload that way, every assignment into a primitive might require additional overhead to check for overloading. But you'd think this would be the case elsewhere as well.<br><br>Well, I'm sure someone knows, but it's not me.  

My interpretation.<BR><BR>If a function modifies the internal data elements of a class instance then it should ideally be a member of that class because this is a basic principle of object-oriented programming. You should not alter the content of objects through external functions but instead declare all mutator functions as members of that class (encapsulate and modularize). I know that it is possible to declare classes to be all public (struct) but doing this is not in keeping with the "ideal" of OO programming...<BR><BR>According to this principle then, an assignment operator is clearly a function that modifies the data elements of a class, so something like this should not be allowed (and is is not):<BR><BR>struct A {<BR> int i;<BR>};<BR><BR>struct B {<BR> int i;<BR>};<BR><BR>A& operator=(A& lhs, const B& rhs) {<BR> lhs.i = rhs.i;<BR> return lhs;<BR>}<BR><BR>By extension, if you agree that you should not be defining external assignment operators outside their class definition, then in order to remain consistent you probably should not be doing this for the basic data types either.<BR><BR>I know that it could be "possible" to allow programmers to write this since structs leave all data accessible to external functions. But then there are many other features that could also be added to C++, features that could be convenient and neat to have. Still, since there has to be an end to what you include in the language, and to what you decide to permit or to forbid, this particular ability may simply be a case of something that was not truly needed and/or not widely requested before the stardard got established. It's not like it prevents programmers from doing what they need to do since it is still possible to write a named function called "assign" that does exactly what is needed, but with less syntactic sugar.<BR><BR>qWake  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by qWake:<BR>My interpretation.<BR><BR>If a function modifies the internal data elements of a class instance then it should ideally be a member of that class because this is a basic principle of object-oriented programming. You should not alter the content of objects through external functions but instead declare all mutator functions as members of that class (encapsulate and modularize). I know that it is possible to declare classes to be all public (struct) but doing this is not in keeping with the "ideal" of OO programming...<BR><BR>According to this principle then, an assignment operator is clearly a function that modifies the data elements of a class, so something like this should not be allowed (and is is not):<BR><BR>struct A {<BR> int i;<BR>};<BR><BR>struct B {<BR> int i;<BR>};<BR><BR>A& operator=(A& lhs, const B& rhs) {<BR> lhs.i = rhs.i;<BR> return lhs;<BR>}<BR><BR>By extension, if you agree that you should not be defining external assignment operators outside their class definition, then in order to remain consistent you probably should not be doing this for the basic data types either.<BR><BR>I know that it could be "possible" to allow programmers to write this since structs leave all data accessible to external functions. But then there are many other features that could also be added to C++, features that could be convenient and neat to have. Still, since there has to be an end to what you include in the language, and to what you decide to permit or to forbid, this particular ability may simply be a case of something that was not truly needed and/or not widely requested before the stardard got established. It's not like it prevents programmers from doing what they need to do since it is still possible to write a named function called "assign" that does exactly what is needed, but with less syntactic sugar.<BR><BR>qWake<HR></BLOCKQUOTE><BR><BR>In your example, it would make sense to put the operator= (A& lhs, const B& rhs) into the class A as a public method, since it modifies the internal data of the instance of A.<BR><BR>What I'm having a problem with is if you want to assign from a class to a primitive. The assignment operator that affects the instance of the class still can go in the class, but the assignment operator that affects the primitive can only go into the global namespace.<BR><BR>For whatever reason, one can not do this as one can with most operators (arithmetic operators, for example, can be made global so that if I want to write MyComplex operator- (const float& lhs, const MyComplex& rhs), I can).<BR><BR>However, there's another way to look at it: we explicitly cast the class to the primitive type, and then we overload the casting operation to do what we want, so our actual expression ends up looking like some_int = (int) MyClass.<BR><BR>Using a function called assign() removes the point of operator overloading. In my particular case, that's important, because I'm making a "replacement" unsigned int that internally keeps track of more information. But when I template over a class, I'd like to be able to switch out MyClass for char and have it still work. I can't do that with assign, because some_char.assign() doesn't work.<BR><BR>I don't profess to have enough C++ experience to know why explicit casting is so preferable (or not impossible) compared to overloading the assigment operator globally as to enforce it in the language spec, but I'm satisfied that the expression I'm trying to write is still possible via explicit casts.<BR><BR>Sidenote: I think you're oversimplifying the OO encapsulation issue. If we believed that external functions should never ever be able to access internal data, then why would we have the friend keyword? Befriending a function <I>increases</I> encapsulation, beccause it allows us to selectively grant access to internal data to certain functions where it makes sense to make them global, but keep the world at large away from our internal data.<BR><BR>I'm not a big fan of OO in general, but the more I think about it, the more I think this whole issue, and my project in particular, makes sense. I'm basically writing a set of tools to do image enhancement, and I'm making an object Pixel that can internally hold some sort of high-resolution data, but be accessed in a more standard form (integer representing grayscale data, etc).<BR><BR><BR>(.mobius)  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>arithmetic operators, for example, can be made global so that if I want to write MyComplex operator- (const float& lhs, const MyComplex& rhs), I can<HR></BLOCKQUOTE><BR><BR>If you are looking for a rationale for this difference, I can suggest this: an external "operator=" function would still need to modify the content of its first parameter as well as return a reference to it. An "operator-" simply returns a newly-constructed instance so it does not require internal access to its first parameter. This difference may be significant enough to warrant disallowing the first while allowing the second. I would have to ask Mr. Stroustrup for specifics...<BR><BR><BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>some_int = (int) MyClass.<HR></BLOCKQUOTE><BR><BR>This looks like the most reasonable approach. If you wanted the language to let you do the same thing without using the cast operator then you would also run into error situations with unrelated classes, like this:<BR><BR>some_int = MyString;<BR><BR>Preventing this would require a C++ compiler to examine the content of the MyString class and see that no "int" cast operator is defined for MyString. I suppose it could be done; more work for the compiler, less for the programmer... It's not the case though, so the explicit cast appears to be the only option. You probably won't find it too annoying considering that you already need to use a cast when assigning a double to an int if you want to prevent warning messages.<BR><BR><BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Befriending a function increases encapsulation<HR></BLOCKQUOTE><BR><BR>This may be an academic consideration where the theoretical principles of OO and the realities of industrial programming are not necessarily reconcilable. An important fact is that C++ is not a strict OO language, it only offers constructs that support OO programming. It also offer a lot of constructs that go against it, and that even against basic structured programming. It still has a "goto" for heaven's sake.<BR><BR>So I would not claim that the 'friend' feature, convenient and expedient as it may be in many situations, increases encapsulation. What it does is relinquish control of the class content to an external function or an external class, and in doing this you do not maintains the "capsule" intact. Don't get me wrong, I am not arguing against using friend functions, and I make use of them whenever convenient. But when I do this I realize that my class is no longer fully encapsulated since any change I make to it must now take into consideration whatever may be happening in a different class or a different function. No big problem from a practical point of view since you can just go there and fix whatever needs to be fixed in that other class. But still the OO principle that a class is self-contained is indeed violated when we do this.<BR><BR><BR>qWake  

Ars Praefectus

  • Jun 26, 2003

Try using this http://www.rafb.net/efnet_cpp/faq/concepts/copyctor/ <BR>as a reference.<BR><BR>Your probably running into a problem with your copy constructor (which you need to define).  

Well-known member

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>This may be an academic consideration where the theoretical principles of OO and the realities of industrial programming are not necessarily reconcilable. An important fact is that C++ is not a strict OO language, it only offers constructs that support OO programming. It also offer a lot of constructs that go against it, and that even against basic structured programming. It still has a "goto" for heaven's sake.<BR><BR>So I would not claim that the 'friend' feature, convenient and expedient as it may be in many situations, increases encapsulation. <HR></BLOCKQUOTE><BR>Not in and of itself, but it can be used to increase encapsulation.  

Smack-Fu Master, in training

  • Jun 27, 2003

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by .mobius:<BR>I'm writing a wrapped data class to allow me to easily convert between several similar datatypes. That is, I have a class MyClass which internally represents an item, but can interact with ints, floats, doubles, all in predefined ways. This is a consummate example of why operator overloading is a Good Thing, right? I can write:<BR><pre class="ip-ubbcode-code-pre"> resultInt = anInt + MyInstance; resultFloat = aFloat + MyInstance; </pre><BR>and it all works transparently to the user of the class. _But_, I can't do what I want with assignment. For example:<BR><pre class="ip-ubbcode-code-pre"> myInt = myInstance; // All good and happy and right. myInstance = myInt; // Apparently not allowed. (Why not?). </pre><BR><BR>To do the second, one would naturally define <pre class="ip-ubbcode-code-pre">operator= (int lhs, const MyClass& rhs);</pre> externally and include it as a friend of MyClass. However, it seems this is not allowed (at least, according to VC++ 6 docs; I haven't tried GCC yet).<BR><BR>Why is this not allowed? How should I handle it instead? I'm at a loss, because I can't think of any other natural way to write this, and I can't find any info online about how to make it work.<BR><BR>Thanks!<BR><BR><BR>(.mobius)<BR><BR>[This message was edited by .mobius on June 25, 2003 at 15:13.]<HR></BLOCKQUOTE><BR><BR>If you put the operator function as a protected member function, you must only pass one param because C++ uses the LHS parameter for purposes of the calling the operator function and implicitly passes "this" as the LHS param. <BR><BR><pre class="ip-ubbcode-code-pre"> int operator=( int rhs ) { return *this.some_var + rhs; //or do whatever you need to. } </pre><BR><BR>or you could declare it outside the class defination and use the friend keyword, when this happens you can declare the function either way because it doesnt need to call the function as a member of the class. So you can do this:<BR><BR><pre class="ip-ubbcode-code-pre"> friend int operator=( MyClass &lhs, int &rhs) friend int operator=( int &lhs, MyClass &rhs) </pre><BR><BR>this way you can write code like the following:<BR><BR><pre class="ip-ubbcode-code-pre"> MyClass = num; num = MyClass; </pre><BR><BR>Hope this helped.<BR><BR>[This message was edited by Arrix on June 27, 2003 at 07:30.]<BR><BR>[This message was edited by Arrix on June 27, 2003 at 07:33.]  

<blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by Arrix-- View image here: http://arstechnica.infopop.net/infopop/emoticons/icon_redface.gif --r you could declare it outside the class defination and use the friend keyword, when this happens you can declare the function either way because it doesnt need to call the function as a member of the class. So you can do this:<br><br><pre class="ip-ubbcode-code-pre"> friend int operator=( MyClass &lhs, int &rhs) friend int operator=( int &lhs, MyClass &rhs) </pre> <br><br>this way you can write code like the following:<br><br><pre class="ip-ubbcode-code-pre"> MyClass = num; num = MyClass; </pre> <br><br>Hope this helped.<br><hr> </blockquote> <br><br>See, but you can't actually do that with the assignment operator. According to VC++ docs:<br><blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr> <br>The assignment operator has some additional restrictions. It can be overloaded only as a nonstatic member function, not as a friend function. It is the only operator that cannot be inherited; a derived class cannot use a base class's assignment operator. <br><hr> </blockquote> <br><br>I'm still curious why one can't overload the assignment operator in this way. Is it due to some inherent difficulty or contradiction in the language that would develop if it were possible? Is it an attempt to force 'good style' on users of the language? Or is it some combination of the two, or something else entirely?<br><br>It's not important to me right now, since I can overload the casting operator and achieve basically the same effect, but I'm interested to head if anyone has insight into the reasoning behind this limitation.  

Seniorius Lurkius

There is so much going on at the compiler level trying to make things work out for casting different things in the most optimal way - that it is probably not worth your time pursuing. <br><br>In the end, even though what your doing looks simple - there are rules that the compiler is trying to interpret and rules get added to rules that get added to rules - until not even the people who write the compiler know for sure what will happen in certain situations.<br><br>So, in the long and short of it, if it works and your sure you've tested your code for all your cases - don't worry about that low level nasty stuff. Cause everyone will have a different answer and none will probably be the same -- View image here: http://arstechnica.infopop.net/infopop/emoticons/icon_wink.gif --  

kenada

Ars Legatus Legionis

AFAIK casts made using the cast operator are implicit unless marked otherwise (at least, this was my experience using GCC 3.0 and GCC 3.2).  

From Eckel's Thinking in C++ 2nd ED, Chapter 12 - Operator Overloading<BR><BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Behavior of operator=<BR><BR>In Integer.h and Byte.h, you saw that operator= can be only a member function. It is intimately connected to the object on the left side of the '='. If it was possible to define operator= globally, then you might attempt to redefine the built-in '=' sign:<BR><BR><BR>int operator=(int, MyType); // Global = not allowed!<BR>The compiler skirts this whole issue by forcing you to make operator= a member function.<BR><BR><BR>When you create an operator=, you must copy all of the necessary information from the right-hand object into the current object (that is, the object that operator= is being called for) to perform whatever you consider 'assignment' for your class. For simple objects, this is obvious:<BR><BR><pre class="ip-ubbcode-code-pre"> //: C12:SimpleAssignment.cpp // Simple operator=() #include <iostream> using namespace std; class Value { int a, b; float c; public: Value(int aa = 0, int bb = 0, float cc = 0.0) : a(aa), b(bb), c(cc) {} Value& operator=(const Value& rv) { a = rv.a; b = rv.b; c = rv.c; return *this; } friend ostream& operator<<(ostream& os, const Value& rv) { return os << "a = " << rv.a << ", b = " << rv.b << ", c = " << rv.c; } }; int main() { Value a, b(1, 2, 3.3); cout << "a: " << a << endl; cout << "b: " << b << endl; a = b; cout << "a after assignment: " << a << endl; } ///:~ </pre><BR>Here, the object on the left side of the = copies all the elements of the object on the right, then returns a reference to itself, which allows a more complex expression to be created.<BR><BR><BR>This example includes a common mistake. When you're assigning two objects of the same type, you should always check first for self-assignment: is the object being assigned to itself? In some cases, such as this one, it's harmless if you perform the assignment operations anyway, but if changes are made to the implementation of the class, it can make a difference, and if you don't do it as a matter of habit, you may forget and cause hard-to-find bugs.<BR><BR><HR></BLOCKQUOTE><BR><BR>Available on-line for free at: <BR><BR> http://mindview.net/Books/DownloadSites  

<blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by .mobius:<br><blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr>Originally posted by Arrix-- View image here: http://arstechnica.infopop.net/infopop/emoticons/icon_redface.gif --r you could declare it outside the class defination and use the friend keyword, when this happens you can declare the function either way because it doesnt need to call the function as a member of the class. So you can do this:<br><br><pre class="ip-ubbcode-code-pre"> friend int operator=( MyClass &lhs, int &rhs) friend int operator=( int &lhs, MyClass &rhs) </pre> <br><br>this way you can write code like the following:<br><br><pre class="ip-ubbcode-code-pre"> MyClass = num; num = MyClass; </pre> <br><br>Hope this helped.<br><hr> </blockquote> <br><br>See, but you can't actually do that with the assignment operator. According to VC++ docs:<br><blockquote class="ip-ubbcode-quote"> <font size="-1">quote:</font><hr> <br>The assignment operator has some additional restrictions. It can be overloaded only as a nonstatic member function, not as a friend function. It is the only operator that cannot be inherited; a derived class cannot use a base class's assignment operator. <br><hr> </blockquote> <br><br>I'm still curious why one can't overload the assignment operator in this way. Is it due to some inherent difficulty or contradiction in the language that would develop if it were possible? Is it an attempt to force 'good style' on users of the language? Or is it some combination of the two, or something else entirely?<br><br>It's not important to me right now, since I can overload the casting operator and achieve basically the same effect, but I'm interested to head if anyone has insight into the reasoning behind this limitation.<hr> </blockquote> <br><br>Ahh yep the assignment operator is "special" in that you can only overload it as a member function just as the VC++ docs says. I totally forgot that. -- View image here: http://arstechnica.infopop.net/OpenTopic/ws/images/judge.gif --  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>When you're assigning two objects of the same type, you should always check first for self-assignment: is the object being assigned to itself? In some cases, such as this one, it's harmless if you perform the assignment operations anyway, but if changes are made to the implementation of the class, it can make a difference, and if you don't do it as a matter of habit, you may forget and cause hard-to-find bugs.<HR></BLOCKQUOTE><BR>Hrm.<BR><BR>The correct way to do it is to perform copy construction and implement a <tt>swap()</tt> member function. This allows one's operator= to provide the strong exception guarantee (which is desirable if possible) at (with a reasonable compiler) no cost to the user.<BR><BR>If one writes one's operator= in this way then the self-assignment check isn't required; it's an <em>optimization</em>, and probably a useful one at that, but it's not required for correct program behaviour.  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>The correct way to do it is to perform copy construction and implement a swap() member function.<HR></BLOCKQUOTE><BR>Can you provide an example, particularly showing what to do with the swap() member function under this scheme?  

  • Jun 28, 2003

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by .mobius:<BR>See, but you can't actually do that with the assignment operator. According to VC++ docs:<BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR><BR>The assignment operator has some additional restrictions. It can be overloaded only as a nonstatic member function, not as a friend function. It is the only operator that cannot be inherited; a derived class cannot use a base class's assignment operator. <BR><HR></BLOCKQUOTE><BR><BR>I'm still curious why one can't overload the assignment operator in this way. Is it due to some inherent difficulty or contradiction in the language that would develop if it were possible? Is it an attempt to force 'good style' on users of the language? Or is it some combination of the two, or something else entirely?<BR><BR>It's not important to me right now, since I can overload the casting operator and achieve basically the same effect, but I'm interested to head if anyone has insight into the reasoning behind this limitation.<HR></BLOCKQUOTE><BR><BR> The reasoning is pretty simple, it's just the way objects and operators relate to each other.<BR> Take the operator+ for instance. Given the statement: obj1+obj2. obj1 and obj2 are added together and it returns (implied)obj3. The same behavior is held for generally the rest of the operators. Each of these operators can be statically defined (to exist outside the scope of the class) as they 1) are type-checked against the class for the apropriate version 2) return a new copy of the object.<BR> Then we have operator=. Which by definition always has the form 'objType = '. This forcefully binds = to the objType. Of which the = operator does not create a new object for the destination which makes logical sense. If we enabled static operator= it would not be illegal to assign a value to a undefined object.  

Ars Tribunus Militum

  • Jul 2, 2003

Overloading the casting operator is generally seen as a bad idea. I believe I first came across the rationale in one of Meyer's Effective C++ books. Basically, when you define casting operators, you run the risk that the compiler will do strange things that you might not expect (in particular with argument passing in functions, IIRC). The recommendation from him was to define a member function asInt() that performs the conversion for you, but doesn't actually change the syntax of the language.<BR><BR>The reason why you can't overload intrinsic types as LHS arguments is to make it easier on programmers to have consistent behavior of intrinsic types. Basically, if you can have operator=(int, Foo), and if you have a constructor like Foo(int), then possible behavior for code:<BR>int x = 42;<BR>could be interpreted by the compiler as:<BR>int x;<BR>operator=(x, Foo(42));<BR>which is probably not what most programmers are expecting when assigning an int to an int.<BR><BR>read Meyers for a more thorough explanation.<BR><BR>--sam  

<BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>Originally posted by qWake:<BR><BLOCKQUOTE class="ip-ubbcode-quote"><font size="-1">quote:</font><HR>The correct way to do it is to perform copy construction and implement a swap() member function.<HR></BLOCKQUOTE><BR>Can you provide an example, particularly showing what to do with the swap() member function under this scheme?<HR></BLOCKQUOTE><BR><pre class="ip-ubbcode-code-pre"> class Foo { public: void swap(Foo& rhs) // nothrow { s.swap(rhs.s); // nothrow std::swap(i, rhs.i); // nothrow c.swap(rhs.c); // nothrow } Foo& operator=(const Foo& rhs) { Foo temp(rhs); // copy construct -- may throw. But if it does, neither *this nor rhs are altered. temp.swap(*this); // nothrow } private: std::string s; int i; SomeOtherClassThatCanSwap c; }; </pre><BR><BR>If you want to perform the self-assignment test, you can. It'll tend to enhance performance a little. But it's not required. By writing the assignment operator in this way we are sure that either the assignment is successful, or the object is left unmodified. The price is some extra copying.  

C++ Operator Overloading Guidelines

One of the nice features of C++ is that you can give special meanings to operators, when they are used with user-defined classes. This is called operator overloading . You can implement C++ operator overloads by providing special member-functions on your classes that follow a particular naming convention. For example, to overload the + operator for your class, you would provide a member-function named operator+ on your class.

  • = (assignment operator)
  • + - * (binary arithmetic operators)
  • += -= *= (compound assignment operators)
  • == != (comparison operators)

Here are some guidelines for implementing these operators. These guidelines are very important to follow, so definitely get in the habit early.

Assignment Operator =

The assignment operator has a signature like this: class MyClass { public: ... MyClass & operator=(const MyClass &rhs); ... } MyClass a, b; ... b = a; // Same as b.operator=(a);

Notice that the = operator takes a const-reference to the right hand side of the assignment. The reason for this should be obvious, since we don't want to change that value; we only want to change what's on the left hand side.

  • e = 42 assigns 42 to e , then returns e as the result
  • The value of e is then assigned to d , and then d is returned as the result
  • The value of d is then assigned to c , and then c is returned as the result

Now, in order to support operator chaining, the assignment operator must return some value. The value that should be returned is a reference to the left-hand side of the assignment.

Notice that the returned reference is not declared const . This can be a bit confusing, because it allows you to write crazy stuff like this: MyClass a, b, c; ... (a = b) = c; // What?? At first glance, you might want to prevent situations like this, by having operator= return a const reference. However, statements like this will work with primitive types. And, even worse, some tools actually rely on this behavior. Therefore, it is important to return a non- const reference from your operator= . The rule of thumb is, "If it's good enough for int s, it's good enough for user-defined data-types."

So, for the hypothetical MyClass assignment operator, you would do something like this: // Take a const-reference to the right-hand side of the assignment. // Return a non-const reference to the left-hand side. MyClass& MyClass::operator=(const MyClass &rhs) { ... // Do the assignment operation! return *this; // Return a reference to myself. } Remember, this is a pointer to the object that the member function is being called on. Since a = b is treated as a.operator=(b) , you can see why it makes sense to return the object that the function is called on; object a is the left-hand side.

But, the member function needs to return a reference to the object, not a pointer to the object. So, it returns *this , which returns what this points at (i.e. the object), not the pointer itself. (In C++, instances are turned into references, and vice versa, pretty much automatically, so even though *this is an instance, C++ implicitly converts it into a reference to the instance.)

Now, one more very important point about the assignment operator:

YOU MUST CHECK FOR SELF-ASSIGNMENT!

This is especially important when your class does its own memory allocation. Here is why: The typical sequence of operations within an assignment operator is usually something like this: MyClass& MyClass::operator=(const MyClass &rhs) { // 1. Deallocate any memory that MyClass is using internally // 2. Allocate some memory to hold the contents of rhs // 3. Copy the values from rhs into this instance // 4. Return *this } Now, what happens when you do something like this: MyClass mc; ... mc = mc; // BLAMMO. You can hopefully see that this would wreak havoc on your program. Because mc is on the left-hand side and on the right-hand side, the first thing that happens is that mc releases any memory it holds internally. But, this is where the values were going to be copied from, since mc is also on the right-hand side! So, you can see that this completely messes up the rest of the assignment operator's internals.

The easy way to avoid this is to CHECK FOR SELF-ASSIGNMENT. There are many ways to answer the question, "Are these two instances the same?" But, for our purposes, just compare the two objects' addresses. If they are the same, then don't do assignment. If they are different, then do the assignment.

So, the correct and safe version of the MyClass assignment operator would be this: MyClass& MyClass::operator=(const MyClass &rhs) { // Check for self-assignment! if (this == &rhs) // Same object? return *this; // Yes, so skip assignment, and just return *this. ... // Deallocate, allocate new space, copy values... return *this; } Or, you can simplify this a bit by doing: MyClass& MyClass::operator=(const MyClass &rhs) { // Only do assignment if RHS is a different object from this. if (this != &rhs) { ... // Deallocate, allocate new space, copy values... } return *this; } Remember that in the comparison, this is a pointer to the object being called, and &rhs is a pointer to the object being passed in as the argument. So, you can see that we avoid the dangers of self-assignment with this check.

  • Take a const-reference for the argument (the right-hand side of the assignment).
  • Return a reference to the left-hand side, to support safe and reasonable operator chaining. (Do this by returning *this .)
  • Check for self-assignment, by comparing the pointers ( this to &rhs ).

Compound Assignment Operators += -= *=

I discuss these before the arithmetic operators for a very specific reason, but we will get to that in a moment. The important point is that these are destructive operators, because they update or replace the values on the left-hand side of the assignment. So, you write: MyClass a, b; ... a += b; // Same as a.operator+=(b) In this case, the values within a are modified by the += operator.

How those values are modified isn't very important - obviously, what MyClass represents will dictate what these operators mean.

The member function signature for such an operator should be like this: MyClass & MyClass::operator+=(const MyClass &rhs) { ... } We have already covered the reason why rhs is a const-reference. And, the implementation of such an operation should also be straightforward.

But, you will notice that the operator returns a MyClass -reference, and a non-const one at that. This is so you can do things like this: MyClass mc; ... (mc += 5) += 3;

Don't ask me why somebody would want to do this, but just like the normal assignment operator, this is allowed by the primitive data types. Our user-defined datatypes should match the same general characteristics of the primitive data types when it comes to operators, to make sure that everything works as expected.

This is very straightforward to do. Just write your compound assignment operator implementation, and return *this at the end, just like for the regular assignment operator. So, you would end up with something like this: MyClass & MyClass::operator+=(const MyClass &rhs) { ... // Do the compound assignment work. return *this; }

As one last note, in general you should beware of self-assignment with compound assignment operators as well. Fortunately, none of the C++ track's labs require you to worry about this, but you should always give it some thought when you are working on your own classes.

Binary Arithmetic Operators + - *

The binary arithmetic operators are interesting because they don't modify either operand - they actually return a new value from the two arguments. You might think this is going to be an annoying bit of extra work, but here is the secret:

Define your binary arithmetic operators using your compound assignment operators.

There, I just saved you a bunch of time on your homeworks.

So, you have implemented your += operator, and now you want to implement the + operator. The function signature should be like this: // Add this instance's value to other, and return a new instance // with the result. const MyClass MyClass::operator+(const MyClass &other) const { MyClass result = *this; // Make a copy of myself. Same as MyClass result(*this); result += other; // Use += to add other to the copy. return result; // All done! } Simple!

Actually, this explicitly spells out all of the steps, and if you want, you can combine them all into a single statement, like so: // Add this instance's value to other, and return a new instance // with the result. const MyClass MyClass::operator+(const MyClass &other) const { return MyClass(*this) += other; } This creates an unnamed instance of MyClass , which is a copy of *this . Then, the += operator is called on the temporary value, and then returns it.

If that last statement doesn't make sense to you yet, then stick with the other way, which spells out all of the steps. But, if you understand exactly what is going on, then you can use that approach.

You will notice that the + operator returns a const instance, not a const reference. This is so that people can't write strange statements like this: MyClass a, b, c; ... (a + b) = c; // Wuh...? This statement would basically do nothing, but if the + operator returns a non- const value, it will compile! So, we want to return a const instance, so that such madness will not even be allowed to compile.

  • Implement the compound assignment operators from scratch, and then define the binary arithmetic operators in terms of the corresponding compound assignment operators.
  • Return a const instance, to prevent worthless and confusing assignment operations that shouldn't be allowed.

Comparison Operators == and !=

The comparison operators are very simple. Define == first, using a function signature like this: bool MyClass::operator==(const MyClass &other) const { ... // Compare the values, and return a bool result. } The internals are very obvious and straightforward, and the bool return-value is also very obvious.

The important point here is that the != operator can also be defined in terms of the == operator, and you should do this to save effort. You can do something like this: bool MyClass::operator!=(const MyClass &other) const { return !(*this == other); } That way you get to reuse the hard work you did on implementing your == operator. Also, your code is far less likely to exhibit inconsistencies between == and != , since one is implemented in terms of the other.

  • 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

operator overloading

Operator overloading, what’s the deal with operator overloading.

It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types.

Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes). Overloaded operators are syntactic sugar for function calls:

What are the benefits of operator overloading?

By overloading standard operators on a class, you can exploit the intuition of the users of that class. This lets users program in the language of the problem domain rather than in the language of the machine.

The ultimate goal is to reduce both the learning curve and the defect rate.

What are some examples of operator overloading?

Here are a few of the many examples of operator overloading:

  • myString + yourString might concatenate two std::string objects
  • myDate++ might increment a Date object
  • a * b might multiply two Number objects
  • a[i] might access an element of an Array object
  • x = *p might dereference a “smart pointer” that “points” to a disk record — it could seek to the location on disk where p “points” and return the appropriate record into x

But operator overloading makes my class look ugly; isn’t it supposed to make my code clearer?

Operator overloading makes life easier for the users of a class , not for the developer of the class!

Consider the following example.

Some people don’t like the keyword operator or the somewhat funny syntax that goes with it in the body of the class itself. But the operator overloading syntax isn’t supposed to make life easier for the developer of a class. It’s supposed to make life easier for the users of the class:

Remember: in a reuse-oriented world, there will usually be many people who use your class, but there is only one person who builds it (yourself); therefore you should do things that favor the many rather than the few.

What operators can/cannot be overloaded?

Most can be overloaded. The only C operators that can’t be are . and ?: (and sizeof , which is technically an operator). C++ adds a few of its own operators, most of which can be overloaded except :: and .* .

Here’s an example of the subscript operator (it returns a reference). First with out operator overloading:

Now the same logic is presented with operator overloading:

Why can’t I overload . (dot), :: , sizeof , etc.?

Most operators can be overloaded by a programmer. The exceptions are

There is no fundamental reason to disallow overloading of ?: . So far the committee just hasn’t seen the need to introduce the special case of overloading a ternary operator. Note that a function overloading expr1?expr2:expr3 would not be able to guarantee that only one of expr2 and expr3 was executed.

sizeof cannot be overloaded because built-in operations, such as incrementing a pointer into an array implicitly depends on it. Consider:

Thus, sizeof(X) could not be given a new and different meaning by the programmer without violating basic language rules.

What about :: ? In N::m neither N nor m are expressions with values; N and m are names known to the compiler and :: performs a (compile time) scope resolution rather than an expression evaluation. One could imagine allowing overloading of x::y where x is an object rather than a namespace or a class, but that would – contrary to first appearances – involve introducing new syntax (to allow expr::expr ). It is not obvious what benefits such a complication would bring.

operator. (dot) could in principle be overloaded using the same technique as used for -> . However, doing so can lead to questions about whether an operation is meant for the object overloading . or an object referred to by . . For example:

This problem can be solved in several ways. So far in standardization, it has not been obvious which way would be best. For more details, see D&E .

Can I define my own operators?

Sorry, no. The possibility has been considered several times, but each time it was decided that the likely problems outweighed the likely benefits.

It’s not a language-technical problem. Even when Stroustrup first considered it in 1983, he knew how it could be implemented. However, the experience has been that when we go beyond the most trivial examples people seem to have subtly different opinions of “the obvious” meaning of uses of an operator. A classical example is a**b**c . Assume that ** has been made to mean exponentiation. Now should a**b**c mean (a**b)**c or a**(b**c) ? Experts have thought the answer was obvious and their friends agreed – and then found that they didn’t agree on which resolution was the obvious one. Such problems seem prone to lead to subtle bugs.

Can I overload operator== so it lets me compare two char[] using a string comparison?

No: at least one operand of any overloaded operator must be of some user-defined type (most of the time that means a class ).

But even if C++ allowed you to do this, which it doesn’t, you wouldn’t want to do it anyway since you really should be using a std::string -like class rather than an array of char in the first place since arrays are evil .

Can I create a operator** for “to-the-power-of” operations?

The names of, precedence of, associativity of, and arity of operators is fixed by the language. There is no operator** in C++, so you cannot create one for a class type.

If you’re in doubt, consider that x ** y is the same as x * (*y) (in other words, the compiler assumes y is a pointer). Besides, operator overloading is just syntactic sugar for function calls. Although this particular syntactic sugar can be very sweet, it doesn’t add anything fundamental. I suggest you overload pow(base,exponent) (a double precision version is in <cmath> ).

By the way, operator^ can work for to-the-power-of, except it has the wrong precedence and associativity.

The previous FAQs tell me which operators I can override; but which operators should I override?

Bottom line: don’t confuse your users.

Remember the purpose of operator overloading: to reduce the cost and defect rate in code that uses your class. If you create operators that confuse your users (because they’re cool, because they make the code faster, because you need to prove to yourself that you can do it; doesn’t really matter why), you’ve violated the whole reason for using operator overloading in the first place.

What are some guidelines / “rules of thumb” for overloading operators?

Here are a few guidelines / rules of thumb (but be sure to read the previous FAQ before reading this list):

  • Use common sense. If your overloaded operator makes life easier and safer for your users, do it; otherwise don’t. This is the most important guideline. In fact it is, in a very real sense, the only guideline; the rest are just special cases.
  • If you define arithmetic operators, maintain the usual arithmetic identities. For example, if your class defines x + y and x - y , then x + y - y ought to return an object that is behaviorally equivalent to x . The term behaviorally equivalent is defined in the bullet on x == y below, but simply put, it means the two objects should ideally act like they have the same state. This should be true even if you decide not to define an == operator for objects of your class.
  • You should provide arithmetic operators only when they make logical sense to users. Subtracting two dates makes sense, logically returning the duration between those dates, so you might want to allow date1 - date2 for objects of your Date class (provided you have a reasonable class/type to represent the duration between two Date objects). However adding two dates makes no sense: what does it mean to add July 4, 1776 to June 5, 1959? Similarly it makes no sense to multiply or divide dates, so you should not define any of those operators.
  • You should provide mixed-mode arithmetic operators only when they make logical sense to users. For example, it makes sense to add a duration (say 35 days) to a date (say July 4, 1776), so you might define date + duration to return a Date . Similarly date - duration could also return a Date . But duration - date does not make sense at the conceptual level (what does it mean to subtract July 4, 1776 from 35 days?) so you should not define that operator.
  • If you provide constructive operators, they should return their result by value. For example, x + y should return its result by value. If it returns by reference, you will probably run into lots of problems figuring out who owns the referent and when the referent will get destructed. Doesn’t matter if returning by reference is more efficient; it is probably wrong . See the next bullet for more on this point.
  • If you provide constructive operators, they should not change their operands. For example, x + y should not change x . For some crazy reason, programmers often define x + y to be logically the same as x += y because the latter is faster. But remember, your users expect x + y to make a copy. In fact they selected the + operator (over, say, the += operator) precisely because they wanted a copy. If they wanted to modify x , they would have used whatever is equivalent to x += y instead. Don’t make semantic decisions for your users; it’s their decision, not yours, whether they want the semantics of x + y vs. x += y . Tell them that one is faster if you want, but then step back and let them make the final decision — they know what they’re trying to achieve and you do not.
  • If you provide constructive operators, they should allow promotion of the left-hand operand (at least in the case where the class has a single-parameter ctor that is not marked with the explicit keyword ). For example, if your class Fraction supports promotion from int to Fraction (via the non- explicit ctor Fraction::Fraction(int) ), and if you allow x - y for two Fraction objects, you should also allow 42 - y . In practice that simply means that your operator-() should not be a member function of Fraction . Typically you will make it a friend , if for no other reason than to force it into the public: part of the class , but even if it is not a friend, it should not be a member.
  • In general, your operator should change its operand(s) if and only if the operands get changed when you apply the same operator to intrinsic types. x == y and x << y should not change either operand; x *= y and x <<= y should (but only the left-hand operand).
  • If you define x++ and ++x , maintain the usual identities. For example, x++ and ++x should have the same observable effect on x , and should differ only in what they return. ++x should return x by reference; x++ should either return a copy (by value) of the original state of x or should have a void return-type. You’re usually better off returning a copy of the original state of x by value, especially if your class will be used in generic algorithms. The easy way to do that is to implement x++ using three lines: make a local copy of *this , call ++x (i.e., this->operator++() ), then return the local copy. Similar comments for x-- and --x .
  • If you define ++x and x += 1 , maintain the usual identities. For example, these expressions should have the same observable behavior, including the same result. Among other things, that means your += operator should return x by reference. Similar comments for --x and x -= 1 .
  • If you define *p and p[0] for pointer-like objects, maintain the usual identities. For example, these two expressions should have the same result and neither should change p .
  • If you define p[i] and *(p+i) for pointer-like objects, maintain the usual identities. For example, these two expressions should have the same result and neither should change p . Similar comments for p[-i] and *(p-i) .
  • Subscript operators generally come in pairs; see on const -overloading .
  • If you define x == y , then x == y should be true if and only if the two objects are behaviorally equivalent. In this bullet, the term “behaviorally equivalent” means the observable behavior of any operation or sequence of operations applied to x will be the same as when applied to y . The term “operation” means methods, friends, operators, or just about anything else you can do with these objects (except, of course, the address-of operator). You won’t always be able to achieve that goal, but you ought to get close, and you ought to document any variances (other than the address-of operator).
  • If you define x == y and x = y , maintain the usual identities. For example, after an assignment, the two objects should be equal. Even if you don’t define x == y , the two objects should be behaviorally equivalent (see above for the meaning of that phrase) after an assignment.
  • If you define x == y and x != y , you should maintain the usual identities. For example, these expressions should return something convertible to bool , neither should change its operands, and x == y should have the same result as !(x != y) , and vice versa.
  • If you define inequality operators like x <= y and x < y , you should maintain the usual identities. For example, if x < y and y < z are both true, then x < z should also be true, etc. Similar comments for x >= y and x > y .
  • If you define inequality operators like x < y and x >= y , you should maintain the usual identities. For example, x < y should have the result as !(x >= y) . You can’t always do that, but you should get close and you should document any variances. Similar comments for x > y and !(x <= y) , etc.
  • Avoid overloading short-circuiting operators: x || y or x && y . The overloaded versions of these do not short-circuit — they evaluate both operands even if the left-hand operand “determines” the outcome, so that confuses users.
  • Avoid overloading the comma operator: x, y . The overloaded comma operator does not have the same ordering properties that it has when it is not overloaded, and that confuses users.
  • Don’t overload an operator that is non-intuitive to your users. This is called the Doctrine of Least Surprise. For example, although C++ uses std::cout << x for printing, and although printing is technically called inserting, and although inserting sort of sounds like what happens when you push an element onto a stack, don’t overload myStack << x to push an element onto a stack. It might make sense when you’re really tired or otherwise mentally impaired, and a few of your friends might think it’s “kewl,” but just say No.
  • Use common sense. If you don’t see “your” operator listed here, you can figure it out. Just remember the ultimate goals of operator overloading: to make life easier for your users, in particular to make their code cheaper to write and more obvious.

Caveat: the list is not exhaustive. That means there are other entries that you might consider “missing.” I know.

Caveat: the list contains guidelines, not hard and fast rules. That means almost all of the entries have exceptions, and most of those exceptions are not explicitly stated. I know.

Caveat: please don’t email me about the additions or exceptions. I’ve already spent way too much time on this particular answer.

How do I create a subscript operator for a Matrix class?

Use operator() rather than operator[] .

When you have multiple subscripts, the cleanest way to do it is with operator() rather than with operator[] . The reason is that operator[] always takes exactly one parameter, but operator() can take any number of parameters (in the case of a rectangular matrix, two parameters are needed).

For example:

Then you can access an element of Matrix m using m(i,j) rather than m[i][j] :

See the next FAQ for more detail on the reasons to use m(i,j) vs. m[i][j] .

Why shouldn’t my Matrix class’s interface look like an array-of-array?

Here’s what this FAQ is really all about: Some people build a Matrix class that has an operator[] that returns a reference to an Array object (or perhaps to a raw array , shudder), and that Array object has an operator[] that returns an element of the Matrix (e.g., a reference to a double ). Thus they access elements of the matrix using syntax like m[i][j] rather than syntax like m(i,j) .

The array-of-array solution obviously works, but it is less flexible than the operator() approach . Specifically, there are easy performance tuning tricks that can be done with the operator() approach that are more difficult in the [][] approach, and therefore the [][] approach is more likely to lead to bad performance, at least in some cases.

For example, the easiest way to implement the [][] approach is to use a physical layout of the matrix as a dense matrix that is stored in row-major form (or is it column-major; I can’t ever remember). In contrast, the operator() approach totally hides the physical layout of the matrix, and that can lead to better performance in some cases.

Put it this way: the operator() approach is never worse than, and sometimes better than, the [][] approach.

  • The operator() approach is never worse because it is easy to implement the dense, row-major physical layout using the operator() approach, so when that configuration happens to be the optimal layout from a performance standpoint, the operator() approach is just as easy as the [][] approach (perhaps the operator() approach is a tiny bit easier, but I won’t quibble over minor nits).
  • The operator() approach is sometimes better because whenever the optimal layout for a given application happens to be something other than dense, row-major, the implementation is often significantly easier using the operator() approach compared to the [][] approach.

As an example of when a physical layout makes a significant difference, a recent project happened to access the matrix elements in columns (that is, the algorithm accesses all the elements in one column, then the elements in another, etc.), and if the physical layout is row-major, the accesses can “stride the cache”. For example, if the rows happen to be almost as big as the processor’s cache size, the machine can end up with a “cache miss” for almost every element access. In this particular project, we got a 20% improvement in performance by changing the mapping from the logical layout (row,column) to the physical layout (column,row).

Of course there are many examples of this sort of thing from numerical methods, and sparse matrices are a whole other dimension on this issue. Since it is, in general, easier to implement a sparse matrix or swap row/column ordering using the operator() approach, the operator() approach loses nothing and may gain something — it has no down-side and a potential up-side.

Use the operator() approach .

I still don’t get it. Why shouldn’t my Matrix class’s interface look like an array-of-array?

The same reasons you encapsulate your data structures, and the same reason you check parameters to make sure they are valid.

A few people use [][] despite its limitations , arguing that [][] is better because it is faster or because it uses C-syntax. The problem with the “it’s faster” argument is that it’s not — at least not on the latest version of two of the world’s best known C++ compilers. The problem with the “uses C-syntax” argument is that C++ is not C. Plus, oh yea, the C-syntax makes it harder to change the data structure and harder to check parameter values.

The point of the previous two FAQs is that m(i,j) gives you a clean, simple way to check all the parameters and to hide (and therefore, if you want to, change) the internal data structure. The world already has way too many exposed data structures and way too many out-of-bounds parameters, and those cost way too much money and cause way too many delays and way too many defects.

Now everybody knows that you are different. You are clairvoyant with perfect knowledge of the future, and you know that no one will ever find any benefit from changing your matrix’s internal data structure. Plus you are a good programmer, unlike those slobs out there that occasionally pass wrong parameters, so you don’t need to worry about pesky little things like parameter checking. But even though you don’t need to worry about maintenance costs (no one ever needs to change your code), there might be one or two other programmers who aren’t quite perfect yet. For them, maintenance costs are high, defects are real, and requirements change. Believe it or not, every once in a while they need to (better sit down) change their code.

Admittedly my thongue wath in my theek. But there was a point. The point was that encapsulation and parameter-checking are not crutches for the weak. It’s smart to use techniques that make encapsulation and/or parameter checking easy. The m(i,j) syntax is one of those techniques.

Having said all that, if you find yourself maintaining a billion-line app where the original team used m[i][j] , or even if you are writing a brand new app and you just plain want to use m[i][j] , you can still encapsulate the data structure and/or check all your parameters. It’s not even that hard. However it does require a level of sophistication that, like it or not, average C++ programmers fear. Fortunately you are not average, so read on.

If you merely want to check parameters, just make sure the outer operator[] returns an object rather than a raw array , then that object’s operator[] can check its parameter in the usual way. Beware that this can slow down your program. In particular, if these inner array-like objects end up allocating their own block of memory for their row of the matrix, the performance overhead for creating / destroying your matrix objects can grow dramatically. The theoretical cost is still O( rows × cols ), but in practice, the overhead of the memory allocator ( new or malloc ) can be much larger than anything else, and that overhead can swamp the other costs. For instance, on two of the world’s best known C++ compilers, the separate-allocation-per-row technique was 10x slower than the one-allocation-for-the-entire-matrix technique . 10% is one thing, 10x is another.

If you want to check the parameters without the above overhead and/or if you want to encapsulate (and possibly change) the matrix’s internal data structure, follow these steps:

  • Add operator()(unsigned row, unsigned col) to the Matrix class.
  • Create nested class Matrix::Row . It should have a ctor with parameters (Matrix& matrix, unsigned row) , and it should store those two values in its this object.
  • Change Matrix::operator[](unsigned row) so it returns an object of class Matrix::Row , e.g., { return Row(*this,row); } .
  • Class Matrix::Row then defines its own operator[](unsigned col) which turns around and calls, you guessed it, Matrix::operator()(unsigned row, unsigned col) . If the Matrix::Row data members are called Matrix& matrix_ and unsigned row_ , the code for Matrix::Row::operator[](unsigned col) will be { return matrix_(row_, col); }

Next you will enable const overloading by repeating the above steps. You will create the const version of the various methods, and you will create a new nested class, probably called Matrix::ConstRow . Don’t forget to use const Matrix& instead of Matrix& .

Final step: find the joker who failed to read the previous FAQ and thonk him in the noggin.

If you have a decent compiler and if you judiciously use inlining , the compiler should optimize away the temporary objects. In other words, the operator[] -approach above will hopefully not be slower than what it would have been if you had directly called Matrix::operator()(unsigned row, unsigned col) in the first place. Of course you could have made your life simpler and avoided most of the above work by directly calling Matrix::operator()(unsigned row, unsigned col) in the first place. So you might as well directly call Matrix::operator()(unsigned row, unsigned col) in the first place.

Should I design my classes from the outside (interfaces first) or from the inside (data first)?

From the outside!

A good interface provides a simplified view that is expressed in the vocabulary of a user . In the case of OO software, the interface is normally the set of public methods of either a single class or a tight group of classes .

First think about what the object logically represents, not how you intend to physically build it. For example, suppose you have a Stack class that will be built by containing a LinkedList :

Should the Stack have a get() method that returns the LinkedList ? Or a set() method that takes a LinkedList ? Or a constructor that takes a LinkedList ? Obviously the answer is No, since you should design your interfaces from the outside-in. I.e., users of Stack objects don’t care about LinkedList s; they care about pushing and popping.

Now for another example that is a bit more subtle. Suppose class LinkedList is built using a linked list of Node objects, where each Node object has a pointer to the next Node :

Should the LinkedList class have a get() method that will let users access the first Node ? Should the Node object have a get() method that will let users follow that Node to the next Node in the chain? In other words, what should a LinkedList look like from the outside? Is a LinkedList really a chain of Node objects? Or is that just an implementation detail? And if it is just an implementation detail, how will the LinkedList let users access each of the elements in the LinkedList one at a time?

The key insight is the realization that a LinkedList is not a chain of Node s. That may be how it is built, but that is not what it is. What it is is a sequence of elements. Therefore the LinkedList abstraction should provide a LinkedListIterator class as well, and that LinkedListIterator might have an operator++ to go to the next element, and it might have a get() / set() pair to access its value stored in the Node (the value in the Node element is solely the responsibility of the LinkedList user, which is why there is a get() / set() pair that allows the user to freely manipulate that value).

Starting from the user’s perspective, we might want our LinkedList class to support operations that look similar to accessing an array using pointer arithmetic:

To implement this interface, LinkedList will need a begin() method and an end() method. These return a LinkedListIterator object. The LinkedListIterator will need a method to go forward, ++p ; a method to access the current element, *p ; and a comparison operator, p != a.end() .

The code follows. The important thing to notice is that LinkedList does not have any methods that let users access Node s. Node s are an implementation technique that is completely buried. This makes the LinkedList class safer (no chance a user will mess up the invariants and linkages between the various nodes), easier to use (users don’t need to expend extra effort keeping the node-count equal to the actual number of nodes, or any other infrastructure stuff), and more flexible (by changing a single typedef , users could change their code from using LinkedList to some other list-like class and the bulk of their code would compile cleanly and hopefully with improved performance characteristics).

Here are the methods that are obviously inlinable (probably in the same header file):

Conclusion: The linked list had two different kinds of data. The values of the elements stored in the linked list are the responsibility of the user of the linked list (and only the user; the linked list itself makes no attempt to prohibit users from changing the third element to 5), and the linked list’s infrastructure data ( next pointers, etc.), whose values are the responsibility of the linked list (and only the linked list; e.g., the linked list does not let users change (or even look at!) the various next pointers).

Thus the only get() / set() methods were to get and set the elements of the linked list, but not the infrastructure of the linked list. Since the linked list hides the infrastructure pointers/etc., it is able to make very strong promises regarding that infrastructure (e.g., if it were a doubly linked list, it might guarantee that every forward pointer was matched by a backwards pointer from the next Node ).

So, we see here an example of where the values of some of a class’s data is the responsibility of users (in which case the class needs to have get() / set() methods for that data) but the data that the class wants to control does not necessarily have get() / set() methods.

Note: the purpose of this example is not to show you how to write a linked-list class. In fact you should not “roll your own” linked-list class since you should use one of the “container classes” provided with your compiler. Ideally you’ll use one of the standard container classes such as the std::list<T> template.

How can I overload the prefix and postfix forms of operators ++ and -- ?

Via a dummy parameter.

Since the prefix and postfix ++ operators can have two definitions, the C++ language gives us two different signatures. Both are called operator++() , but the prefix version takes no parameters and the postfix version takes a dummy int . (Although this discussion revolves around the ++ operator, the -- operator is completely symmetric, and all the rules and guidelines that apply to one also apply to the other.)

Note the different return types: the prefix version returns by reference, the postfix version by value. If that’s not immediately obvious to you, it should be after you see the definitions (and after you remember that y = x++ and y = ++x set y to different things).

The other option for the postfix version is to return nothing:

However you must not make the postfix version return the this object by reference; you have been warned.

Here’s how you use these operators:

Assuming the return types are not ‘void’, you can use them in larger expressions:

Which is more efficient: i++ or ++i ?

++i is sometimes faster than, and is never slower than, i++ .

For intrinsic types like int , it doesn’t matter: ++i and i++ are the same speed. For class types like iterators or the previous FAQ’s Number class, ++i very well might be faster than i++ since the latter might make a copy of the this object.

The overhead of i++ , if it is there at all, won’t probably make any practical difference unless your app is CPU bound. For example, if your app spends most of its time waiting for someone to click a mouse, doing disk I/O, network I/O, or database queries, then it won’t hurt your performance to waste a few CPU cycles. However it’s just as easy to type ++i as i++ , so why not use the former unless you actually need the old value of i .

So if you’re writing i++ as a statement rather than as part of a larger expression, why not just write ++i instead? You never lose anything, and you sometimes gain something. Old line C programmers are used to writing i++ instead of ++i . E.g., they’ll say, for (i = 0; i < 10; i++) ... . Since this uses i++ as a statement, not as a part of a larger expression, then you might want to use ++i instead. For symmetry, I personally advocate that style even when it doesn’t improve speed, e.g., for intrinsic types and for class types with postfix operators that return void .

Obviously when i++ appears as a part of a larger expression, that’s different: it’s being used because it’s the only logically correct solution, not because it’s an old habit you picked up while programming in C.

Please Login to submit a recommendation.

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

  • Windows Programming
  • UNIX/Linux Programming
  • General C++ Programming
  • operator overload outside of classes

  operator overload outside of classes

c assignment operator outside class

std; throttle { : throttle( tPos = 6, cPos = 0) { Top_Position = tPos; position = cPos; } throttle copy(throttle t) { Top_Position = t.getTop(); position = t.getPos(); } getTop() { Top_Position; } getPos() { position; } ==(throttle t) { ((Top_Position == t.getTop()) && (position == t.getPos())); } : position; Top_Position; }; main() { throttle car; throttle truck(30); throttle shuttle(20, 6); throttle mythrottle(truck); (car. ==(truck)) cout << << endl; cout << << endl; (car == truck) cout << << endl; cout << << endl; ( !=(car, truck)) cout << << endl; cout << << endl; 0; } !=( throttle& t1, throttle& t2) { ((t1.getTop() != t2.getTop()) && (t1.getPos() != t2.getTop())); }
std; throttle { : throttle( tPos = 6, cPos = 0) { Top_Position = tPos; position = cPos; } throttle copy(throttle t) { Top_Position = t.getTop(); position = t.getPos(); } getTop() { Top_Position; } getPos() { position; } ==(throttle t) { ((Top_Position == t.getTop()) && (position == t.getPos())); } : position; Top_Position; }; main() { throttle car; throttle truck(30); throttle shuttle(20, 6); throttle mythrottle(truck); (car. ==(truck)) cout << << endl; cout << << endl; (car == truck) cout << << endl; cout << << endl; ( !=(car, truck))
  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Copy Constructor vs Assignment Operator in C++

Copy constructor and Assignment operator are similar as they are both used to initialize one object using another object. But, there are some basic differences between them:

Copy constructor  Assignment operator 
It is called when a new object is created from an existing object, as a copy of the existing object This operator is called when an already initialized object is assigned a new value from another existing object. 
It creates a separate memory block for the new object. It does not create a separate memory block or new memory space.
It is an overloaded constructor. It is a bitwise operator. 
C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. 

className(const className &obj) {

// body 

}

 

className obj1, obj2;

obj2 = obj1;

Consider the following C++ program. 

Explanation: Here, t2 = t1;  calls the assignment operator , same as t2.operator=(t1); and   Test t3 = t1;  calls the copy constructor , same as Test t3(t1);

Must Read: When is a Copy Constructor Called in C++?

Please Login to comment...

Similar reads, improve your coding skills with practice.

 alt=

What kind of Experience do you want to share?

cppreference.com

Nested classes.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
General topics
(C++11)
-
-expression
block


/
(C++11)
(C++11)
(C++11)
(C++20)
(C++20)
(C++11)

expression
pointer
specifier

specifier (C++11)
specifier (C++11)
(C++11)

(C++11)
(C++11)
(C++11)
General
/ types
types
Members
pointer
-declarations
(C++11)
specifier
specifier
Special member functions
(C++11)
(C++11)
Inheritance
specifier (C++11)
specifier (C++11)

A declaration of a class/struct or union may appear within another class. Such declaration declares a nested class .

[ edit ] Explanation

The name of the nested class exists in the scope of the enclosing class, and name lookup from a member function of a nested class visits the scope of the enclosing class after examining the scope of the nested class. Like any member of its enclosing class, the nested class has access to all names (private, protected, etc) to which the enclosing class has access, but it is otherwise independent and has no special access to the this pointer of the enclosing class. Declarations in a nested class can use any members of the enclosing class, following the usual usage rules for the non-static members.

Friend functions defined within a nested class have no special access to the members of the enclosing class even if lookup from the body of a member function that is defined within a nested class can find the private members of the enclosing class.

Out-of-class definitions of the members of a nested class appear in the namespace of the enclosing class:

Nested classes can be forward-declared and later defined, either within the same enclosing class body, or outside of it:

Nested class declarations obey member access specifiers, a private member class cannot be named outside the scope of the enclosing class, although objects of that class may be manipulated:

[ edit ] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
C++98 the members of a nested class cannot
access the enclosing class and its friends
they have the same access rights as
other members of the enclosing class
(also resolves CWG issues #8 and #10)

[ edit ] References

  • C++23 standard (ISO/IEC 14882:2024):
  • 11.4.12 Nested class declarations [class.nest]
  • C++20 standard (ISO/IEC 14882:2020):
  • 11.4.10 Nested class declarations [class.nest]
  • C++17 standard (ISO/IEC 14882:2017):
  • 12.2.5 Nested class declarations [class.nest]
  • C++14 standard (ISO/IEC 14882:2014):
  • 9.7 Nested class declarations [class.nest]
  • C++11 standard (ISO/IEC 14882:2011):
  • C++98 standard (ISO/IEC 14882:1998):
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 17 May 2023, at 12:12.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

Copy constructors and copy assignment operators (C++)

  • 8 contributors

Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment . In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++) .

Both the assignment operation and the initialization operation cause objects to be copied.

Assignment : When one object's value is assigned to another object, the first object is copied to the second object. So, this code copies the value of b into a :

Initialization : Initialization occurs when you declare a new object, when you pass function arguments by value, or when you return by value from a function.

You can define the semantics of "copy" for objects of class type. For example, consider this code:

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows:

Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x); .

Use the copy constructor.

If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you. Similarly, if you don't declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor doesn't suppress the compiler-generated copy assignment operator, and vice-versa. If you implement either one, we recommend that you implement the other one, too. When you implement both, the meaning of the code is clear.

The copy constructor takes an argument of type ClassName& , where ClassName is the name of the class. For example:

Make the type of the copy constructor's argument const ClassName& whenever possible. This prevents the copy constructor from accidentally changing the copied object. It also lets you copy from const objects.

Compiler generated copy constructors

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name ." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name & . In such a case, the compiler-generated copy constructor's argument is also const .

When the argument type to the copy constructor isn't const , initialization by copying a const object generates an error. The reverse isn't true: If the argument is const , you can initialize by copying an object that's not const .

Compiler-generated assignment operators follow the same pattern for const . They take a single argument of type ClassName& unless the assignment operators in all base and member classes take arguments of type const ClassName& . In this case, the generated assignment operator for the class takes a const argument.

When virtual base classes are initialized by copy constructors, whether compiler-generated or user-defined, they're initialized only once: at the point when they are constructed.

The implications are similar to the copy constructor. When the argument type isn't const , assignment from a const object generates an error. The reverse isn't true: If a const value is assigned to a value that's not const , the assignment succeeds.

For more information about overloaded assignment operators, see Assignment .

Was this page helpful?

Coming soon: Throughout 2024 we will be phasing out GitHub Issues as the feedback mechanism for content and replacing it with a new feedback system. For more information see: https://aka.ms/ContentUserFeedback .

Submit and view feedback for

Additional resources

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

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.

Operator overloading inside vs outside class [duplicate]

What is the difference between inside and outside class overloading?

  • operator-overloading

Michael Oks's user avatar

  • 1 If it's possible to do it outside, then do it outside. But why would you compare to a pointer? So you want obj1 == &obj2 ? No sense. –  Ivaylo Valchev Commented Jan 10, 2017 at 7:42
  • Try using either. They don't do the same thing. –  juanchopanza Commented Jan 10, 2017 at 7:42

First consider this example using your class (reformatted to a style I prefer):

  • Since the argument is a pointer, the client code must apply & .
  • Since the method is not const , objects that are const can not be compared.

The conventional way to do this is therefore to pass the argument by reference, and to make the method const :

If you define the comparison outside the class, like this:

… then

  • The definition guaranteed does not depend on internal implementation details of class B , that conceivably could change in the future.
  • Also the first argument can be a value that converts implicitly to B .
  • You can, if you want, have formal arguments of different types, where the class only appears in the second argument, like this:

If you choose to place these non-member operators inline inside the class definition, via the friend mechanism (so that they're found via ADL lookup), then you lose the first bullet point's advantage, but you then have all the code relevant for use of the class, within the class definition:

Cheers and hth. - Alf's user avatar

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

  • Featured on Meta
  • Announcing a change to the data-dump process
  • We've made changes to our Terms of Service & Privacy Policy - July 2024

Hot Network Questions

  • Substitute for saltpetre
  • ESTA renewal advice
  • Expected cards drawn before first ace and king
  • How to export a variable in Mathematica to .mat format such that MATLAB loads the file, the data is imported to something not called Expression1
  • What is the color of the final disc(s)?
  • Research Faculty with no salary
  • "Man cannot live by bread alone." — Is there any logical explanation why this idiom doesn't have an article before "man"?
  • How to reinstall a ceiling fan that fell out of ceiling?
  • How can I disable highlighting of matching symbols in expression in version 14.1?
  • Efficient way to remove nailed-down plywood flooring in attic without damaging it?
  • How is the name "Took" pronounced?
  • What kind of navy could island nations with populations in the few 100k range build to fight eachother in a 1890s-1920s century naval technology?
  • Can I restrict which users can `sendmail` from an address with Postfix?
  • Are there non-religious variants of moral realism that defend the existence of objectively evil thoughts, intentions, and desires?
  • Sci-fi/robot/alien movie in which a woman runs into an abandoned home to escape a four-legged robot
  • What's a simple proof for solutions to a non homogeneous 2nd order linear recurrence relation?
  • What would a planet need to have a sustained blood-based water cycle?
  • ^ symbol in music theory
  • The difference between ii°7 and vii°7
  • How can I count frequency of a list faster?
  • Is believing the role of man in John 3:16? Is believing not by Holy Spirit work?
  • DC motor pump always transports in same direction, regardless of polarity
  • Any idea what game this picture is from?
  • Accessing an overridden Greek letter

c assignment operator outside class

IMAGES

  1. Assignment Operators in C » PREP INSTA

    c assignment operator outside class

  2. Assignment Operators in C/C++

    c assignment operator outside class

  3. C# Assignment Operator

    c assignment operator outside class

  4. [100% Working Code]

    c assignment operator outside class

  5. Assignment Operator in C

    c assignment operator outside class

  6. Assignment Operators in C++

    c assignment operator outside class

VIDEO

  1. NPTEL Problem Solving Through Programming In C Week 0 Quiz Assignment Solution

  2. Assignment Operator in C Programming

  3. Assignment Operator in C Programming

  4. Augmented assignment operators in C

  5. NPTEL Problem Solving through Programming in C ASSIGNMENT 6 ANSWERS 2024

  6. #7 Operators and its Types in C Language (Part 1) with Notes

COMMENTS

  1. c++

    24. First: the two different ways are really "overload as a member" and "overload as a non-member", and the latter has two different ways to write it (as-friend-inside class definition and outside class definition). Calling them "inside class" and "outside class" is going to confuse you. Overloads for +=, +, -=, -, etc. have a special pattern:

  2. 21.12

    21.12 — Overloading the assignment operator. Alex July 22, 2024. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. As of C++11, C++ also supports "Move assignment". We discuss move assignment in lesson 22.3 -- Move constructors and move assignment .

  3. Assignment operators

    for assignments to class type objects, the right operand could be an initializer list only when the assignment is defined by a user-defined assignment operator. removed user-defined assignment constraint. CWG 1538. C++11. E1 ={E2} was equivalent to E1 = T(E2) ( T is the type of E1 ), this introduced a C-style cast. it is equivalent to E1 = T{E2}

  4. C Programming Assignment Operators

    Assignment Operators in C are used to assign values to the variables. They come under the category of binary operators as they require two operands to operate upon. The left side operand is called a variable and the right side operand is the value. The value on the right side of the "=" is assigned to the variable on the left side of "=".

  5. C Assignment Operators

    Code language:C++(cpp) The = assignment operator is called a simple assignment operator. It assigns the value of the left operand to the right operand. Besides the simple assignment operator, C supports compound assignment operators. A compound assignment operator performs the operation specified by the additional operator and then assigns the ...

  6. Assignment Operators in C

    Simple assignment operator. Assigns values from right side operands to left side operand. C = A + B will assign the value of A + B to C. +=. Add AND assignment operator. It adds the right operand to the left operand and assign the result to the left operand. C += A is equivalent to C = C + A. -=.

  7. Copy assignment operator

    5,6) Definition of a copy assignment operator outside of class definition (the class must contain a declaration (1) ). 6) The copy assignment operator is explicitly-defaulted. The copy assignment operator is called whenever selected by overload resolution, e.g. when an object appears on the left side of an assignment expression.

  8. Overloading assignments (C++ only)

    Overloading assignments (C++ only) You overload the assignment operator, operator=, with a nonstatic member function that has only one parameter. You cannot declare an overloaded assignment operator that is a nonmember function. The following example shows how you can overload the assignment operator for a particular class: struct X {. int data;

  9. How to define an assignment operator outside my header file in C++

    I have a header file which contains a class with an assignment operator. Now I want to define my function inside my .cpp file. My header file contains: Car &operator=(const Car &other); Now in my cpp file I would like to do something like: Car::Car &operator=(const Car &other) {. } Unfortunately this doesn't seem to be the right syntax.

  10. [C++] Why can't I externally overload operator= with my class on the

    The assignment operator that affects the instance of the class still can go in the class, but the assignment operator that affects the primitive can only go into the global namespace.<BR><BR>For ...

  11. C++ Operator Overloading Guidelines

    You can implement C++ operator overloads by providing special member-functions on your classes that follow a particular naming convention. For example, to overload the + operator for your class, you would provide a member-function named operator+ on your class. The following set of operators is commonly overloaded for user-defined classes:

  12. C++ Assignment Operator Overloading

    The assignment operator,"=", is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types. Assignment operator overloading is binary operator overloading. Overloading assignment operator in C++ copies all values of one object to another object.

  13. operator overloading

    When an operator appears in an expression, and at least one of its operands has a class type or an enumeration type, then overload resolution is used to determine the user-defined function to be called among all the functions whose signatures match the following: Expression. As member function. As non-member function.

  14. Operator Overloading

    It allows you to provide an intuitive interface to users of your class, plus makes it possible for templates to work equally well with classes and built-in/intrinsic types. Operator overloading allows C/C++ operators to have user-defined meanings on user-defined types (classes). Overloaded operators are syntactic sugar for function calls: class ...

  15. operator overload outside of classes

    I read that and understand how to write an overload function like that using a member function inside a class, but I need to be able to write a regular function outside of a class that can do the same thing.

  16. Copy Constructor vs Assignment Operator in C++

    C++ compiler implicitly provides a copy constructor, if no copy constructor is defined in the class. A bitwise copy gets created, if the Assignment operator is not overloaded. Consider the following C++ program. Explanation: Here, t2 = t1; calls the assignment operator, same as t2.operator= (t1); and Test t3 = t1; calls the copy constructor ...

  17. Nested classes

    Explanation. The name of the nested class exists in the scope of the enclosing class, and name lookup from a member function of a nested class visits the scope of the enclosing class after examining the scope of the nested class. Like any member of its enclosing class, the nested class has access to all names (private, protected, etc) to which ...

  18. Copy constructors and copy assignment operators (C++)

    Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x);. Use the copy constructor. If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you.

  19. c++

    auto operator==( int const u, B const& v ) -> bool { return true; // Whatever. } If you choose to place these non-member operators inline inside the class definition, via the friend mechanism (so that they're found via ADL lookup), then you lose the first bullet point's advantage, but you then have all the code relevant for use of the class ...