21.12 — Overloading the assignment operator
- 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
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.]
More options
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 --
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.
- Windows Programming
- UNIX/Linux Programming
- General C++ Programming
- operator overload outside of classes
operator overload outside of classes
cppreference.com
Copy assignment operator.
A copy assignment operator is a non-template non-static member function with the name operator = that can be called with an argument of the same class type and copies the content of the argument without mutating the argument.
[ edit ] Syntax
For the formal copy assignment operator syntax, see function declaration . The syntax list below only demonstrates a subset of all valid copy assignment operator syntaxes.
[ edit ] Explanation
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.
[ edit ] Implicitly-declared copy assignment operator
If no user-defined copy assignment operators are provided for a class type, the compiler will always declare one as an inline public member of the class. This implicitly-declared copy assignment operator has the form T & T :: operator = ( const T & ) if all of the following is true:
- each direct base B of T has a copy assignment operator whose parameters are B or const B & or const volatile B & ;
- each non-static data member M of T of class type or array of class type has a copy assignment operator whose parameters are M or const M & or const volatile M & .
Otherwise the implicitly-declared copy assignment operator is declared as T & T :: operator = ( T & ) .
Due to these rules, the implicitly-declared copy assignment operator cannot bind to a volatile lvalue argument.
A class can have multiple copy assignment operators, e.g. both T & T :: operator = ( T & ) and T & T :: operator = ( T ) . If some user-defined copy assignment operators are present, the user may still force the generation of the implicitly declared copy assignment operator with the keyword default . (since C++11)
The implicitly-declared (or defaulted on its first declaration) copy assignment operator has an exception specification as described in dynamic exception specification (until C++17) noexcept specification (since C++17)
Because the copy assignment operator is always declared for any class, the base class assignment operator is always hidden. If a using-declaration is used to bring in the assignment operator from the base class, and its argument type could be the same as the argument type of the implicit assignment operator of the derived class, the using-declaration is also hidden by the implicit declaration.
[ edit ] Implicitly-defined copy assignment operator
If the implicitly-declared copy assignment operator is neither deleted nor trivial, it is defined (that is, a function body is generated and compiled) by the compiler if odr-used or needed for constant evaluation (since C++14) . For union types, the implicitly-defined copy assignment copies the object representation (as by std::memmove ). For non-union class types, the operator performs member-wise copy assignment of the object's direct bases and non-static data members, in their initialization order, using built-in assignment for the scalars, memberwise copy-assignment for arrays, and copy assignment operator for class types (called non-virtually).
[ edit ] Deleted copy assignment operator
An implicitly-declared or explicitly-defaulted (since C++11) copy assignment operator for class T is undefined (until C++11) defined as deleted (since C++11) if any of the following conditions is satisfied:
- T has a non-static data member of a const-qualified non-class type (or possibly multi-dimensional array thereof).
- T has a non-static data member of a reference type.
- T has a potentially constructed subobject of class type M (or possibly multi-dimensional array thereof) such that the overload resolution as applied to find M 's copy assignment operator
- does not result in a usable candidate, or
- in the case of the subobject being a variant member , selects a non-trivial function.
[ edit ] Trivial copy assignment operator
The copy assignment operator for class T is trivial if all of the following is true:
- it is not user-provided (meaning, it is implicitly-defined or defaulted);
- T has no virtual member functions;
- T has no virtual base classes;
- the copy assignment operator selected for every direct base of T is trivial;
- the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial.
A trivial copy assignment operator makes a copy of the object representation as if by std::memmove . All data types compatible with the C language (POD types) are trivially copy-assignable.
[ edit ] Eligible copy assignment operator
Triviality of eligible copy assignment operators determines whether the class is a trivially copyable type .
[ edit ] Notes
If both copy and move assignment operators are provided, overload resolution selects the move assignment if the argument is an rvalue (either a prvalue such as a nameless temporary or an xvalue such as the result of std::move ), and selects the copy assignment if the argument is an lvalue (named object or a function/operator returning lvalue reference). If only the copy assignment is provided, all argument categories select it (as long as it takes its argument by value or as reference to const, since rvalues can bind to const references), which makes copy assignment the fallback for move assignment, when move is unavailable.
It is unspecified whether virtual base class subobjects that are accessible through more than one path in the inheritance lattice, are assigned more than once by the implicitly-defined copy assignment operator (same applies to move assignment ).
See assignment operator overloading for additional detail on the expected behavior of a user-defined copy-assignment operator.
[ edit ] Example
[ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
[ edit ] See also
- converting constructor
- copy constructor
- copy elision
- default constructor
- aggregate initialization
- constant initialization
- copy initialization
- default initialization
- direct initialization
- initializer list
- list initialization
- reference initialization
- value initialization
- zero initialization
- move assignment
- move constructor
- 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 2 February 2024, at 15:13.
- Privacy policy
- About cppreference.com
- Disclaimers
C++ overloading: operators to overload as methods of a class
Become a Software Engineer in Months, Not Years
From your first line of code, to your first day on the job — Educative has you covered. Join 2M+ developers learning in-demand programming skills.
Operator overloading is an interesting topic of object-oriented programming using C++. Operator overloading enables the objects of a class to be used in expressions. Some operators must be overloaded as non-static member functions of the class. This blog discusses these operators with coding examples.
Let’s dive right in!
We’ll cover:
- Introduction
- Assignment operators
- Single overload
- Two ways to overload
- Noninteger index
- Function call operator
- Operators that are preferred as members
- Wrapping up and next steps
Introduction #
Operators are overloaded as functions in C++. They can be overloaded in various ways: as member functions only, as nonmembers only, and as both members and nonmembers. Here, we discuss the operators that can be overloaded as non-static member functions only. The first operand or the caller of these operators is always an object of the class. Other aspects related to operator overloading are discussed in Operator Overloading in C++ and Various Ways of Overloading an Operator in C++ .
Operators that can’t be nonmembers #
There are a few operators in C++ that must be overloaded as member functions of the class. The courses C++ Programming for Experienced Engineers and Data Structures Preliminaries (Refresher of Fundamentals in C++) discuss the topic of C++ operator overloading in greater detail. We’re discussing only the following operators here:
Assignment operator ( = )
Subscript operator ( [] )
Function call operator ( () )
The caller object (the first operand) of all these operators is always an object of the class. Therefore, there’s no reason for their overloading from outside the class. We are using the example of an Array class that can store an array of integers. Initially, the Array class has the following members:
It has an int data member size to store the length of the array.
It has a pointer data member to store the int values.
It also has a constructor that can be invoked with one or two parameters. The first parameter specifies the size of the array to be allocated. The second parameter specifies the initial value to be assigned to all the elements of the array .
If you’re looking to sharpen up your C++ programming skills, then you’re in the right place. You will start with learning about dynamic memory allocation, how to create classes, and constructors. In the latter half of the course, inheritance, functions, I/O, exception handling, and more. Throughout the course, you will study over 90 carefully designed examples aimed to enhance your understanding of the C++ language. By the time you finish this course, you will be able to use more advanced functionality in your C++ programs.
Assignment operator #
The assignment operator has two operands. The first operand is on the left-hand side of the operator, therefore termed the left-hand side (LHS). The second operand is on the right-hand side of the operator, therefore termed the right-hand side (RHS). The LHS is always a variable and is also termed LValue in this context. The type of LHS is always the class for which we want to overload the operator. The RHS can be a constant, variable, or expression. The type of RHS depends on the usage scenario that we want to permit to be assigned to the object.
The simplest (placeholder) overload of the assignment operator is given below to demonstrate the permissible overloading. We overload it for object-to-object assignment. It means that both the objects (LHS and RHS) are of the same type.
In the code above:
Lines 4–31: We define the Array class as having two data members and five methods.
Line 28: We provide an empty definition of the overloaded assignment operator just to emphasize its header.
Line 30: This is a commented line that indicates that the assignment operator can’t be overloaded as a static method. Uncommenting this line gives an error.
Line 33: This is also a commented line to indicate that the assignment operator can’t be defined outside the class (as a nonmember). Removing the // at the start causes an error in the program.
Lines 35–43: We define the main() function of the program to demonstrate the correct execution.
Line 36: We instantiate an object a to have a size 5 and the value 1 in all the elements of the array.
Line 37: We show the array values stored in a .
Line 38: We instantiate another object b to have a size 8 and the value 2 in all the elements of the array.
Line 39: We show the array values stored in b .
Line 40: We call the overloaded assignment operator, which has an empty body for the time being.
Line 41: We show the unchanged values of b because the overloaded assignment operator defined in the class does nothing.
If we don’t overload the assignment operator, then the default behavior provided by the language does the member-wise (or bit-wise) assignment of RHS onto LHS.
Commenting line 28 in the code above will cause an error due to the member-wise assignment provided by the default implementation of the assignment operator.
The following is the complete code to illustrate the overloaded assignment operator for the Array class. The overloaded operator performs the complete assignment and returns the LHS object with its updated values. Returning the object provides the facility of cascading or chaining , as in a = b = c; . For the successful execution of this expression, the result of b = c must return a value that can be stored in a . The cascading or chaining gets blocked if the operator has the return type void and returns nothing. Still, it can correctly perform the assignment.
Let’s start from the main() function in the above code:
Line 52: We invoke the overloaded assignment operator, where b is the calling object (LHS) and a is the parameter (RHS). The parameter is received as a const reference to the object for time and space efficiency.
Line 59: We demonstrate a cascaded call to the assignment operator. The assignment operator works from right to left . In the first step, d = a is called, then its result is sent as a parameter to the second call.
Now, let’s look at the working of the operator =() method:
Lines 38–39: First, we compare the size attribute of both objects (LHS and RHS). If the sizes are different, we call the resize() method to allocate the new memory to the calling object after deallocating its previously allocated one.
Line 41: Inside the loop, we copy each element of the RHS array to the LHS array elements.
Line 43: We return the updated value of the calling object through *this .
The following section discusses the peculiarities of implementing the subscript operator.
Data Structures Preliminaries (Refresher of Fundamentals in C++)
Dive into a comprehensive review of the fundamental elements of C++ through this course. Experience concise yet detailed explanations, coupled with hands-on exercises that delve into the core concepts of C++ fundamentals. Your journey begins with the exploration of fundamental programming concepts, such as the versatility of variables and their applications in strengthening control structures like conditions, loops, arrays and pointers. Next, you’ll cover structured programming, understanding its advantages and disadvantages, which seamlessly transitions you into object-oriented programming (OOP). Your focus will expand to encompass subjects like classes, object relationships and the implementation of operator overloading to equip user-defined data types. By the end of this course, you'll possess a solid grasp of the essential fundamentals, providing a robust foundation for success in subsequent courses, including the study of data structures and algorithms in C++.
Subscript operator #
The following two subsections extend the Array class to illustrate the overloading of the subscript operator with a typical use case of an integer index. We throw an exception to indicate that the index value is out of range. The concluding part of this section illustrates the use of a noninteger index, like a map container , through overloading the subscript operator.
Two ways to overload #
There are two versions of a subscript operator: RValue and LValue. The following code demonstrates overloading the RValue usage for the Array class. In this scenario, we can use the subscript operator only on the RHS of the assignment.
Let’s start from the main() function in the code above:
Line 42: We invoke the overloaded subscript operator, where a is the calling object and 3 is the parameter. The operator returns the value at index 3 of the array data member in object a .
Line 46: Uncommenting this line causes an error due to the absence of RValue overload of the subscript operator. This line is commented to enable the successful execution of the remaining code.
Now, let’s look at the working of the subscript operator ( lines 30–34 ):
Line 30: The return type of the operator is int because we want to return the value of an element from the integer array attribute arr of the calling object a . The parameter int index gets the value 3 . We declare this method const as it doesn’t change the calling object.
Line 31: We validate the value of the index . If it’s not within the boundaries, the next statement throws a predefined exception. C++ uses zero-based indexing, so the valid index values are from 0 to size - 1 .
Line 32: We throw an out_of_range exception to indicate the issue. To use this predefined exception, we wrote #include <stdexcept> at the start of our program.
Line 33: We return the desired element of the array attribute. This statement executes when the index is within the limit as per the array size .
The following code illustrates the peculiarities of implementing the subscript operator for LValue usage. In this scenario, we can use the subscript operator on the LHS of an assignment statement.
We’re using a cout statement inside the overloaded operators to demonstrate their calling sequence for the reader. It’s not recommended for a normal overloading of these operators.
Line 56: We invoke the overloaded RValue subscript operator, where a constant object c is the caller and 3 is the parameter. The operator returns the value at index 3 of the array data member in the object c . We can directly use c[3] in the cout statement instead of storing it in a separate variable, val .
Line 60: We invoke the overloaded LValue subscript operator, where a is the calling object and 3 is the parameter. The operator returns the reference of the array element at index 3 in object a . The reference allows the RHS value to be stored in that element.
Line 64: Uncommenting this line causes an error because a const object can’t be modified. This line is commented to enable the successful execution of the remaining code.
Now, let’s look at both overloaded implementations of the subscript operator ( lines 31–36 and lines 39–44 ):
Line 31: The return type of the operator is int& because we want to return the reference of an element from the integer array attribute arr of the calling object a . The parameter int index gets the value 3 . We can’t declare this method const to permit a modification in the object value. The body of this method is exactly the same as discussed in the previous code.
Line 39: The return type of the operator is int because we want to return the value of an element from the integer array attribute arr of the const calling object c . The parameter int index gets the value 3 . We must declare this method const to permit its call from a const object. The body of this method is exactly the same as demonstrated in the previous code.
Using a reference return type allows the change in the data member of an object. Therefore, such methods can’t be declared const .
The next subsection illustrates a single overload of the subscript operator that can work for LValue and RValue uses for non-constant objects. In this scenario, we can use it on both sides of an assignment statement.
Returning a reference to the private data of an object is a breach of encapsulation.
Single overload #
Yes, we can carry two faces under one hood. The LValue implementation given above can suffice both calls for non-constant objects. The following code illustrates the use of a single implementation for both uses (LValue and RValue).
Lines 30–34: This is the single overloaded operator that’s called for both uses.
Line 42: This is the RValue use of the subscript operator.
Line 45: This is the LValue use of the subscript operator.
Line 48: This is what happens at the end: we show the updated value of the object.
Noninteger index #
Since we use an integer index for an array in C++, most of the time, it’s easy to perceive the usefulness of an integer parameter for the subscript operator. However, a noninteger parameter is also used with the subscript operator as an index.
The subscript operator is a binary operator. It must be defined for two operands only (neither more nor less). However, the type of the second operand can vary.
We use the example of the Time class for illustration. This class has the following members:
Three private data members, h , m , and s , to store the values of hours, minutes, and seconds, respectively.
Three private setter methods, setH() , setM() , and setS() , to modify the values of hours, minutes, and seconds, respectively, within the permissible value ranges.
A public constructor that receives three parameters to initialize the data members. It invokes the setter methods (for reusability and maintenance convenience).
A public method, show() , to display the values of data members separated by : . The fancy details of the display are ignored for simplicity and focus.
From this point onward, we’ll keep using and extending this minimal implementation of the Time class.
Lines 6–29: We define a Time class as described before the code. Additionally, it defines the subscript operator ( lines 21–28 ).
- Line 21: This receives a string parameter to mention the specific attribute that we want to access for read/write. It accepts only "hour" , "minute" , or "second" as an argument. It throws an exception if it receives any other string.
Lines 31–43: We define the main() function that creates an object noon of type Time .
Line 36: We call the subscript operator to read the value of "hour" from noon .
Line 39: We call the subscript operator to write the value of "second" to noon .
Zero to Hero in C++
C++ is a robust and flexible language commonly used for games, desktop, and embedded applications development. This Skill Path is perfect for beginners eager to learn C++ and embark on a programming journey. You’ll explore C++ fundamentals, starting with basic syntax and functionality to create programs, and then dive into more complex concepts like dynamic memory allocation in C++. The latter half focuses on C++ programming with a detailed overview of object-oriented programming (OOP), which includes classes in C++, data hiding in C++, encapsulation in C++, abstraction in C++, inheritance in C++, and polymorphism in C++. Hands-on practice with algorithms and data structures will empower you to write real-world programs confidently, paving your way as a C++ developer.
Function call operator #
There’s another bracket operator ( () ) in C++. It’s termed the function call operator. It’s much more versatile. It allows for any type and any number of parameters. The following code demonstrates its five variations:
No parameter: It works as the show() method demonstrated above.
One parameter: It works with one parameter for two distinct functionalities.
An int parameter: It’s a variant of show() that displays the values in 12-hour format.
A string parameter: It works as the subscript operator demonstrated above.
Two parameters, string and int : It works as a setter method using an integer value for the string— "hour" , "minute" , or "second" .
Three parameters: It receives three int parameters and updates all three data members with them.
The function call operator ( () ) has no restriction on parameters. It can be overloaded for any number of parameters of any type.
The following code demonstrates the implementation and usage of the abovementioned five variations of the function call operator.
Lines 19–21: We define the function call operator with no parameters. It’s just a renamed version of the show() method demonstrated above.
Lines 23–30: We define the function call operator with an int parameter. We don’t use the parameter inside the function body, so we don’t use a variable name for it. We simply use the presence of the argument to display the time using the AM / PM format.
Lines 32–39: We define the function call operator with a string parameter. We use it as the RValue version of the subscript operator. It returns the value of a specific data member based on the received string: "hour" , "minute" , or "second" . In the case of any other string, it throws an out_of_range exception. If we set the return type of this operator to int& , it can also behave as an LValue implementation of the subscript operator.
Lines 41–48: We define the function call operator with two parameters. We use it as the setter method for each data member. It modifies the value of a specific data member with the received int parameter based on the received string: "hour" , "minute" , or "second" . In the case of any other string, it also throws an out_of_range exception.
Lines 50–54: We define the function call operator with three parameters for the corresponding data members. We use it as the setter method for all data members in a single call.
In main() :
Line 58: We create a noon object of the Time type.
Line 61: We call the function call operator with no parameters for noon to display the current value of the data members.
Line 64: We call the function call operator with a string argument "hour" to obtain the hour’s value of noon .
Lines 67–68: We call the function call operator with two arguments to set the values of seconds and minutes in the noon object to 30 and 17 , respectively.
Line 71: We call the function call operator with no parameters for noon to display the current value of data members in the AM / PM format.
Line 74: We call the function call operator with three arguments to set the values of hours, minutes, and seconds in the noon object to 10 , 20 , and 30 , respectively.
Line 77: We call the function call operator with no parameters for the noon object again to display the current value of the data members.
Due to the versatility of the function call operator, its usage makes programs difficult to understand without a standard reading.
Become a C++ Programmer
C++ is a popular language used to develop browsers, games, and operating systems. It's also an essential tool in the development of modern technology like IoT and self-driving cars. This Path will expand your knowledge of C++ with lessons built for professional developers. This Path will take you from basic to advanced concepts with hands-on practice. By the end, you'll have enough C++ experience to confidently solve real-world problems.
Operators that are preferred as members #
The compound assignment ( += , %= , and &= , etc.) and unary ( - , ~ , and ! , etc.) operators always have an object as their first operand. The language doesn’t restrict them from being overloaded as nonmember functions. However, it’s better to keep them inside the class in support of encapsulation.
Wrapping up and next steps #
Some operators can’t be overloaded as nonmembers, e.g., assignment, subscript, and function call operators. The caller (the first operand) or these operators is always an object of the class. Therefore, there’s no point in overloading them as nonmembers.
The function call operator has no restriction on the number and the types of its parameters. The Standard Template Library (STL) uses this powerful feature of the language. Such objects that have overloaded function call operators are called functor objects .
Compound assignment and unary operators can be overloaded as nonmembers and members of the class despite the fact that their caller (the first operand) is also an object of the class. It’s a good programming practice to overload them as members.
Keep exploring, keep overloading, and happy learning!
To start learning these concepts and more, check out Educative’s Data Structures Preliminaries (Refresher of Fundamentals in C++) course.
Continue learning to code #
Free Resources
Learn in-demand tech skills in half the time
Mock Interview
Skill Paths
Assessments
Learn to Code
Tech Interview Prep
Generative AI
Data Science
Machine Learning
GitHub Students Scholarship
Early Access Courses
For Individuals
Try for Free
Gift a Subscription
Become an Author
Become an Affiliate
Earn Referral Credits
Cheatsheets
Frequently Asked Questions
Privacy Policy
Cookie Policy
Terms of Service
Business Terms of Service
Data Processing Agreement
Grokking the Modern System Design Interview
Grokking the Product Architecture Design Interview
Grokking the Coding Interview Patterns
Machine Learning System Design
Copyright © 2024 Educative, Inc. All rights reserved.
C Data Types
C operators.
- C Input and Output
- C Control Flow
C Functions
- C Preprocessors
C File Handling
- C Cheatsheet
C Interview Questions
Assignment operators in c.
Assignment operators are used for assigning value to a variable. The left side operand of the assignment operator is a variable and right side operand of the assignment operator is a value. The value on the right side must be of the same data-type of the variable on the left side otherwise the compiler will raise an error.
Different types of assignment operators are shown below:
1. “=”: This is the simplest assignment operator. This operator is used to assign the value on the right to the variable on the left. Example:
2. “+=” : This operator is combination of ‘+’ and ‘=’ operators. This operator first adds the current value of the variable on left to the value on the right and then assigns the result to the variable on the left. Example:
If initially value stored in a is 5. Then (a += 6) = 11.
3. “-=” This operator is combination of ‘-‘ and ‘=’ operators. This operator first subtracts the value on the right from the current value of the variable on left and then assigns the result to the variable on the left. Example:
If initially value stored in a is 8. Then (a -= 6) = 2.
4. “*=” This operator is combination of ‘*’ and ‘=’ operators. This operator first multiplies the current value of the variable on left to the value on the right and then assigns the result to the variable on the left. Example:
If initially value stored in a is 5. Then (a *= 6) = 30.
5. “/=” This operator is combination of ‘/’ and ‘=’ operators. This operator first divides the current value of the variable on left by the value on the right and then assigns the result to the variable on the left. Example:
If initially value stored in a is 6. Then (a /= 2) = 3.
Below example illustrates the various Assignment Operators:
Similar Reads
- C Programming Language Tutorial In this C Tutorial, you’ll learn all C programming basic to advanced concepts like variables, arrays, pointers, strings, loops, etc. This C Programming Tutorial is designed for both beginners as well as experienced professionals, who’re looking to learn and enhance their knowledge of the C programmi 8 min read
- C Language Introduction C is a procedural programming language initially developed by Dennis Ritchie in the year 1972 at Bell Laboratories of AT&T Labs. It was mainly developed as a system programming language to write the UNIX operating system. The main features of the C language include: General Purpose and PortableL 6 min read
- Features of C Programming Language C is a procedural programming language. It was initially developed by Dennis Ritchie in the year 1972. It was mainly developed as a system programming language to write an operating system. The main features of C language include low-level access to memory, a simple set of keywords, and a clean styl 3 min read
- C Programming Language Standard Introduction:The C programming language has several standard versions, with the most commonly used ones being C89/C90, C99, C11, and C18. C89/C90 (ANSI C or ISO C) was the first standardized version of the language, released in 1989 and 1990, respectively. This standard introduced many of the featur 6 min read
- C Hello World Program The “Hello World” program is the first step towards learning any programming language and also one of the simplest programs you will learn. To print the "Hello World", we can use the printf function from the stdio.h library that prints the given string on the screen. C Program to Print "Hello World" 2 min read
- Compiling a C Program: Behind the Scenes The compilation is the process of converting the source code of the C language into machine code. As C is a mid-level language, it needs a compiler to convert it into an executable code so that the program can be run on our machine. The C program goes through the following phases during compilation: 4 min read
- C Comments The comments in C are human-readable explanations or notes in the source code of a C program. A comment makes the program easier to read and understand. These are the statements that are not executed by the compiler or an interpreter. It is considered to be a good practice to document our code using 3 min read
- Tokens in C A token in C can be defined as the smallest individual element of the C programming language that is meaningful to the compiler. It is the basic component of a C program. Types of Tokens in CThe tokens of C language can be classified into six types based on the functions they are used to perform. Th 5 min read
- Keywords in C In C Programming language, there are many rules so to avoid different types of errors. One of such rule is not able to declare variable names with auto, long, etc. This is all because these are keywords. Let us check all keywords in C language. What are Keywords?Keywords are predefined or reserved w 13 min read
C Variables and Constants
- C Variables A variable in C language is the name associated with some memory location to store data of different types. There are many types of variables in C depending on the scope, storage class, lifetime, type of data they store, etc. A variable is the basic building block of a C program that can be used in 9 min read
- Constants in C The constants in C are the read-only variables whose values cannot be modified once they are declared in the C program. The type of constant can be an integer constant, a floating pointer constant, a string constant, or a character constant. In C language, the const keyword is used to define the con 6 min read
- Const Qualifier in C The qualifier const can be applied to the declaration of any variable to specify that its value will not be changed (which depends upon where const variables are stored, we may change the value of the const variable by using a pointer). The result is implementation-defined if an attempt is made to c 7 min read
- Different ways to declare variable as constant in C There are many different ways to make the variable as constant in C. Some of the popular ones are: Using const KeywordUsing MacrosUsing enum Keyword1. Using const KeywordThe const keyword specifies that a variable or object value is constant and can't be modified at the compilation time. Syntaxconst 2 min read
- Scope rules in C The scope of a variable in C is the block or the region in the program where a variable is declared, defined, and used. Outside this region, we cannot access the variable, and it is treated as an undeclared identifier. The scope is the area under which a variable is visible.The scope of an identifie 6 min read
- Internal Linkage and External Linkage in C It is often quite hard to distinguish between scope and linkage, and the roles they play. This article focuses on scope and linkage, and how they are used in C language. Note: All C programs have been compiled on 64 bit GCC 4.9.2. Also, the terms "identifier" and "name" have been used interchangeabl 9 min read
- Global Variables in C Prerequisite: Variables in C In a programming language, each variable has a particular scope attached to them. The scope is either local or global. This article will go through global variables, their advantages, and their properties. The Declaration of a global variable is very similar to that of a 3 min read
- Data Types in C Each variable in C has an associated data type. It specifies the type of data that the variable can store like integer, character, floating, double, etc. Each data type requires different amounts of memory and has some specific operations which can be performed over it. The data types in C can be cl 7 min read
- Literals in C In C, Literals are the constant values that are assigned to the variables. Literals represent fixed values that cannot be modified. Literals contain memory but they do not have references as variables. Generally, both terms, constants, and literals are used interchangeably. For example, “const int = 4 min read
- Escape Sequence in C The escape sequence in C is the characters or the sequence of characters that can be used inside the string literal. The purpose of the escape sequence is to represent the characters that cannot be used normally using the keyboard. Some escape sequence characters are the part of ASCII charset but so 6 min read
- bool in C The bool in C is a fundamental data type in most that can hold one of two values: true or false. It is used to represent logical values and is commonly used in programming to control the flow of execution in decision-making statements such as if-else statements, while loops, and for loops. In this a 6 min read
- Integer Promotions in C Some data types like char , short int take less number of bytes than int, these data types are automatically promoted to int or unsigned int when an operation is performed on them. This is called integer promotion. For example no arithmetic calculation happens on smaller types like char, short and e 2 min read
- Character Arithmetic in C As already known character range is between -128 to 127 or 0 to 255. This point has to be kept in mind while doing character arithmetic. What is Character Arithmetic?Character arithmetic is used to implement arithmetic operations like addition, subtraction, multiplication, and division on characters 2 min read
- Type Conversion in C Type conversion in C is the process of converting one data type to another. The type conversion is only performed to those data types where conversion is possible. Type conversion is performed by a compiler. In type conversion, the destination data type can't be smaller than the source data type. Ty 5 min read
C Input/Output
- Basic Input and Output in C C language has standard libraries that allow input and output in a program. The stdio.h or standard input output library in C that has methods for input and output. scanf()The scanf() method, in C, reads the value from the console as per the type specified and store it in the given address. Syntax: 3 min read
- Format Specifiers in C The format specifier in C is used to tell the compiler about the type of data to be printed or scanned in input and output operations. They always start with a % symbol and are used in the formatted string in functions like printf(), scanf, sprintf(), etc. The C language provides a number of format 6 min read
- printf in C In C language, printf() function is used to print formatted output to the standard output stdout (which is generally the console screen). The printf function is a part of the C standard library <stdio.h> and it can allow formatting the output in numerous ways. Syntax of printfprintf ( "formatt 5 min read
- scanf in C In C programming language, scanf is a function that stands for Scan Formatted String. It is used to read data from stdin (standard input stream i.e. usually keyboard) and then writes the result into the given arguments. It accepts character, string, and numeric data from the user using standard inpu 2 min read
- Scansets in C scanf family functions support scanset specifiers which are represented by %[]. Inside scanset, we can specify single character or range of characters. While processing scanset, scanf will process only those characters which are part of scanset. We can define scanset by putting characters inside squ 2 min read
- Formatted and Unformatted Input/Output functions in C with Examples This article focuses on discussing the following topics in detail- Formatted I/O Functions.Unformatted I/O Functions.Formatted I/O Functions vs Unformatted I/O Functions.Formatted I/O Functions Formatted I/O functions are used to take various inputs from the user and display multiple outputs to the 9 min read
- Operators in C In C language, operators are symbols that represent operations to be performed on one or more operands. They are the basic components of the C programming. In this article, we will learn about all the built-in operators in C with examples. What is a C Operator?An operator in C can be defined as the 14 min read
- Arithmetic Operators in C Arithmetic Operators are the type of operators in C that are used to perform mathematical operations in a C program. They can be used in programs to define expressions and mathematical formulas. What are C Arithmetic Operators?The C arithmetic operators are the symbols that are used to perform mathe 7 min read
- Unary operators in C Unary operators are the operators that perform operations on a single operand to produce a new value. Types of unary operatorsTypes of unary operators are mentioned below: Unary minus ( - )Increment ( ++ )Decrement ( -- )NOT ( ! )Addressof operator ( & )sizeof()1. Unary MinusThe minus operator ( 5 min read
- Relational Operators in C In C, relational operators are the symbols that are used for comparison between two values to understand the type of relationship a pair of numbers shares. The result that we get after the relational operation is a boolean value, that tells whether the comparison is true or false. Relational operato 4 min read
- Bitwise Operators in C In C, the following 6 operators are bitwise operators (also known as bit operators as they work at the bit-level). They are used to perform bitwise operations in C. The & (bitwise AND) in C takes two numbers as operands and does AND on every bit of two numbers. The result of AND is 1 only if bot 7 min read
- C Logical Operators Logical operators in C are used to combine multiple conditions/constraints. Logical Operators returns either 0 or 1, it depends on whether the expression result is true or false. In C programming for decision-making, we use logical operators. We have 3 logical operators in the C language: Logical AN 6 min read
- Assignment Operators in C Assignment operators are used for assigning value to a variable. The left side operand of the assignment operator is a variable and right side operand of the assignment operator is a value. The value on the right side must be of the same data-type of the variable on the left side otherwise the compi 3 min read
- Increment and Decrement Operators in C The increment ( ++ ) and decrement ( -- ) operators in C are unary operators for incrementing and decrementing the numeric values by 1 respectively. The incrementation and decrementation are one of the most frequently used operations in programming for looping, array traversal, pointer arithmetic, a 4 min read
- Conditional or Ternary Operator (?:) in C The conditional operator in C is kind of similar to the if-else statement as it follows the same algorithm as of if-else statement but the conditional operator takes less space and helps to write the if-else statements in the shortest way possible. It is also known as the ternary operator in C as it 3 min read
- sizeof operator in C Sizeof is a much-used operator in the C. It is a compile-time unary operator which can be used to compute the size of its operand. The result of sizeof is of the unsigned integral type which is usually denoted by size_t. sizeof can be applied to any data type, including primitive types such as integ 4 min read
- Operator Precedence and Associativity in C The concept of operator precedence and associativity in C helps in determining which operators will be given priority when there are multiple operators in the expression. It is very common to have multiple operators in C language and the compiler first evaluates the operater with higher precedence. 8 min read
C Control Statements Decision-Making
- Decision Making in C (if , if..else, Nested if, if-else-if ) The conditional statements (also known as decision control structures) such as if, if else, switch, etc. are used for decision-making purposes in C programs. They are also known as Decision-Making Statements and are used to evaluate one or more conditions and make the decision whether to execute a s 11 min read
- C - if Statement The if in C is the most simple decision-making statement. It consists of the test condition and if block or body. If the given condition is true only then the if block will be executed. What is if in C? The if in C is a decision-making statement that is used to execute a block of code based on the v 5 min read
- C if...else Statement The if-else statement in C is a flow control statement used for decision-making in the C program. It is one of the core concepts of C programming. It is an extension of the if in C that includes an else block along with the already existing if block. C if Statement The if statement in C is used to e 6 min read
- C if else if ladder if else if ladder in C programming is used to test a series of conditions sequentially. Furthermore, if a condition is tested only when all previous if conditions in the if-else ladder are false. If any of the conditional expressions evaluate to be true, the appropriate code block will be executed, 3 min read
- Switch Statement in C Switch case statement evaluates a given expression and based on the evaluated value(matching a certain condition), it executes the statements associated with it. Basically, it is used to perform different actions based on different conditions(cases). Switch case statements follow a selection-control 8 min read
- Using Range in switch Case in C You all are familiar with switch case in C, but did you know you can use a range of numbers instead of a single number or character in the case statement? Range in switch case can be useful when we want to run the same set of statements for a range of numbers so that we do not have to write cases se 2 min read
- C - Loops Loops in programming are used to repeat a block of code until the specified condition is met. A loop statement allows programmers to execute a statement or group of statements multiple times without repetition of code. [GFGTABS] C // C program to illustrate need of loops #include <stdio.h> int 6 min read
- C for Loop In C programming, loops are responsible for performing repetitive tasks using a short code block that executes until the condition holds true. In this article, we will learn about for loop in C. for Loop in CThe for loop in C Language provides a functionality/feature to repeat a set of statements a 6 min read
- while loop in C The while Loop is an entry-controlled loop in C programming language. This loop can be used to iterate a part of code while the given condition remains true. Syntax The while loop syntax is as follows: while (test expression) { // body consisting of multiple statements }Example The below example sho 3 min read
- do...while Loop in C Loops in C language are the control flow statements that are used to repeat some part of the code till the given condition is satisfied. The do-while loop is one of the three loop statements in C, the others being while loop and for loop. It is mainly used to traverse arrays, vectors, and other data 7 min read
- For Versus While Question: Is there any example for which the following two loops will not work the same way? [GFGTABS] C /*Program 1 --> For loop*/ for (<init - stmnt>;<boolean - expr>;<incr - stmnt>) { <body-statements> } /*Program 2 --> While loop*/ <init - stmnt>; while (<b 2 min read
- Continue Statement in C The continue statement in C is a jump statement that is used to bring the program control to the start of the loop. We can use the continue statement in the while loop, for loop, or do..while loop to alter the normal flow of the program execution. Unlike break, it cannot be used with a C switch case 5 min read
- Break Statement in C The break statement is one of the four jump statements in the C language. The purpose of the break statement in C is for unconditional exit from the loop What is break in C?The break in C is a loop control statement that breaks out of the loop when encountered. It can be used inside loops or switch 6 min read
- goto Statement in C The C goto statement is a jump statement which is sometimes also referred to as an unconditional jump statement. The goto statement can be used to jump from anywhere to anywhere within a function. Syntax: Syntax1 | Syntax2----------------------------goto label; | label: . | .. | .. | .label: | goto 3 min read
- C Functions A function in C is a set of statements that when called perform some specific tasks. It is the basic building block of a C program that provides modularity and code reusability. The programming statements of a function are enclosed within { } braces, having certain meanings and performing certain op 10 min read
- User-Defined Function in C A user-defined function is a type of function in C language that is defined by the user himself to perform some specific task. It provides code reusability and modularity to our program. User-defined functions are different from built-in functions as their working is specified by the user and no hea 6 min read
- Parameter Passing Techniques in C In C, there are different ways in which parameter data can be passed into and out of methods and functions. Let us assume that a function B() is called from another function A(). In this case, A is called the "caller function" and B is called the "called function or callee function". Also, the argum 5 min read
- Function Prototype in C The C function prototype is a statement that tells the compiler about the function's name, its return type, numbers and data types of its parameters. By using this information, the compiler cross-checks function parameters and their data type with function definition and function call. Function prot 5 min read
- How can I return multiple values from a function? We all know that a function in C can return only one value. So how do we achieve the purpose of returning multiple values. Well, first take a look at the declaration of a function. int foo(int arg1, int arg2); So we can notice here that our interface to the function is through arguments and return v 2 min read
- main Function in C The main function is an integral part of the programming languages such as C, C++, and Java. The main function in C is the entry point of a program where the execution of a program starts. It is a user-defined function that is mandatory for the execution of a program because when a C program is exec 4 min read
- Implicit return type int in C Predict the output of following C program. #include <stdio.h> fun(int x) { return x*x; } int main(void) { printf("%d", fun(10)); return 0; } Output: 100 The important thing to note is, there is no return type for fun(), the program still compiles and runs fine in most of the C compil 1 min read
- Callbacks in C A callback is any executable code that is passed as an argument to another code, which is expected to call back (execute) the argument at a given time. In simple language, If a reference of a function is passed to another function as an argument to call it, then it will be called a Callback function 2 min read
- Nested functions in C Some programmer thinks that defining a function inside an another function is known as "nested function". But the reality is that it is not a nested function, it is treated as lexical scoping. Lexical scoping is not valid in C because the compiler cant reach/find the correct memory location of the i 2 min read
- Variadic functions in C Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed. The variadic function consists of at least one fixed variable and then an 3 min read
- _Noreturn function specifier in C The _Noreturn keyword appears in a function declaration and specifies that the function does not return by executing the return statement or by reaching the end of the function body. If the function declared _Noreturn returns, the behavior is undefined. A compiler diagnostic is recommended if this c 2 min read
- Predefined Identifier __func__ in C Before we start discussing __func__, let us write some code snippets and anticipate the output: C/C++ Code // C program to demonstrate working of a // Predefined Identifier __func__ #include <stdio.h> int main() { // %s indicates that the program will read strings printf("%s", __func 2 min read
- C Library math.h Functions The math.h header defines various C mathematical functions and one macro. All the functions available in this library take double as an argument and return double as the result. Let us discuss some important C math functions one by one. C Math Functions1. double ceil (double x) The C library functio 6 min read
C Arrays & Strings
- C Arrays Array in C is one of the most used data structures in C programming. It is a simple and fast way of storing multiple values under a single name. In this article, we will study the different aspects of array in C language such as array declaration, definition, initialization, types of arrays, array s 15+ min read
- Properties of Array in C An array in C is a fixed-size homogeneous collection of elements stored at a contiguous memory location. It is a derived data type in C that can store elements of different data types such as int, char, struct, etc. It is one of the most popular data types widely used by programmers to solve differe 8 min read
- Multidimensional Arrays in C - 2D and 3D Arrays Prerequisite: Arrays in C A multi-dimensional array can be defined as an array that has more than one dimension. Having more than one dimension means that it can grow in multiple directions. Some popular multidimensional arrays are 2D arrays and 3D arrays. In this article, we will learn about multid 10 min read
- Initialization of Multidimensional Array in C In C, initialization of a multidimensional array can have left most dimensions as optional. Except for the leftmost dimension, all other dimensions must be specified. For example, the following program fails in compilation because two dimensions are not specified. C/C++ Code #include <stdio.h> 2 min read
- Pass Array to Functions in C In C, the whole array cannot be passed as an argument to a function. However, you can pass a pointer to an array without an index by specifying the array's name. Arrays in C are always passed to the function as pointers pointing to the first element of the array. SyntaxIn C, we have three ways to pa 6 min read
- How to pass a 2D array as a parameter in C? This post is an extension of How to dynamically allocate a 2D array in C? A one dimensional array can be easily passed as a pointer, but syntax for passing a 2D array to a function can be difficult to remember. One important thing for passing multidimensional arrays is, first array dimension does no 4 min read
- What are the data types for which it is not possible to create an array? In C, it is possible to have array of all types except following. 1) void. 2) functions. For example, below program throws compiler error int main() { void arr[100]; } Output: error: declaration of 'arr' as array of voids But we can have array of void pointers and function pointers. The below progra 1 min read
- How to pass an array by value in C ? In C, array name represents address and when we pass an array, we actually pass address and the parameter receiving function always accepts them as pointers (even if we use [], refer this for details). How to pass array by value, i.e., how to make sure that we have a new copy of array when we pass i 2 min read
- Strings in C A String in C programming is a sequence of characters terminated with a null character '\0'. The C String is stored as an array of characters. The difference between a character array and a C string is that the string in C is terminated with a unique character '\0'. C String Declaration SyntaxDeclar 8 min read
- Array of Strings in C In C programming String is a 1-D array of characters and is defined as an array of characters. But an array of strings in C is a two-dimensional array of character types. Each String is terminated with a null character (\0). It is an application of a 2d array. Syntax: char variable_name[r][m] = {lis 3 min read
- What is the difference between single quoted and double quoted declaration of char array? In C, when a character array is initialized with a double-quoted string and the array size is not specified, the compiler automatically allocates one extra space for string terminator '\0'. Example The below example demonstrates the initialization of a char array with a double-quoted string without 2 min read
- C String Functions The C string functions are built-in functions that can be used for various operations and manipulations on strings. These string functions can be used to perform tasks such as string copy, concatenation, comparison, length, etc. The <string.h> header file contains these string functions. In th 8 min read
- C Pointers A pointer is defined as a derived data type that can store the memory address of other variables, functions, or even other pointers. It is one of the core components of the C programming language allowing low-level memory access, dynamic memory allocation, and many other functionalities in C. Syntax 10 min read
- Pointer Arithmetics in C with Examples Pointer Arithmetic is the set of valid arithmetic operations that can be performed on pointers. The pointer variables store the memory address of another variable. It doesn't store any value. Hence, there are only a few operations that are allowed to perform on Pointers in C language. The C pointer 10 min read
- C - Pointer to Pointer (Double Pointer) Prerequisite: Pointers in C The pointer to a pointer in C is used when we want to store the address of another pointer. The first pointer is used to store the address of the variable. And the second pointer is used to store the address of the first pointer. That is why they are also known as double- 5 min read
- Function Pointer in C In C, like normal data pointers (int *, char *, etc), we can have pointers to functions. Following is a simple example that shows declaration and function call using function pointer. Let's take a look at an example: [GFGTABS] C #include <stdio.h> void fun(int a) { printf("Value of a is % 5 min read
- How to declare a pointer to a function? While a pointer to a variable or an object is used to access them indirectly, a pointer to a function is used to invoke a function indirectly. Well, we assume that you know what it means by a pointer in C. So how do we create a pointer to an integer in C? Huh..it is pretty simple... int *ptrInteger; 2 min read
- Pointer to an Array | Array Pointer A pointer to an array is a pointer that points to the whole array instead of the first element of the array. It considers the whole array as a single unit instead of it being a collection of given elements. Consider the following example: [GFGTABS] C #include<stdio.h> int main() { int arr[5] = 5 min read
- Difference between constant pointer, pointers to constant, and constant pointers to constants In this article, we will discuss the differences between constant pointer, pointers to constant & constant pointers to constants. Pointers are the variables that hold the address of some other variables, constants, or functions. There are several ways to qualify pointers using const. Pointers to 3 min read
- Pointer vs Array in C Most of the time, pointer and array accesses can be treated as acting the same, the major exceptions being: 1. the sizeof operator sizeof(array) returns the amount of memory used by all elements in the array sizeof(pointer) only returns the amount of memory used by the pointer variable itself 2. the 1 min read
- Dangling, Void , Null and Wild Pointers in C In C programming pointers are used to manipulate memory addresses, to store the address of some variable or memory location. But certain situations and characteristics related to pointers become challenging in terms of memory safety and program behavior these include Dangling (when pointing to deall 6 min read
- Near, Far and Huge Pointers in C In older times, the intel processors had 16-bit registers but the address bus was 20-bits wide. Due to this, the registers were not able to hold the entire address at once. As a solution, the memory was divided into segments of 64 kB size, and the near pointers, far pointers, and huge pointers were 4 min read
- restrict keyword in C In the C programming language (after the C99 standard), a new keyword is introduced known as restrict. restrict keyword is mainly used in pointer declarations as a type qualifier for pointers.It doesn't add any new functionality. It is only a way for the programmer to inform about an optimization th 2 min read
C User-Defined Data Types
- C Structures The structure in C is a user-defined data type that can be used to group items of possibly different types into a single type. The struct keyword is used to define the structure in the C programming language. The items in the structure are called its member and they can be of any valid data type. Ad 10 min read
- dot (.) Operator in C The C dot (.) operator is used for direct member selection via the name of variables of type struct and union. Also known as the direct member access operator, it is a binary operator that helps us to extract the value of members of the structures and unions. Syntax of Dot Operatorvariable_name.memb 2 min read
- C typedef The typedef is a keyword that is used to provide existing data types with a new name. The C typedef keyword is used to redefine the name of already existing data types. When names of datatypes become difficult to use in programs, typedef is used with user-defined datatypes, which behave similarly to 4 min read
- Structure Member Alignment, Padding and Data Packing In C, the structures are used as data packs. They don't provide any data encapsulation or data hiding features. In this article, we will discuss the property of structure padding in C along with data alignment and structure packing. Data Alignment in MemoryEvery data type in C will have alignment re 12 min read
- Flexible Array Members in a structure in C Flexible Array Member(FAM) is a feature introduced in the C99 standard of the C programming language. For the structures in C programming language from C99 standard onwards, we can declare an array without a dimension and whose size is flexible in nature.Such an array inside the structure should pre 4 min read
- C Unions The Union is a user-defined data type in C language that can contain elements of the different data types just like structure. But unlike structures, all the members in the C union are stored in the same memory location. Due to this, only one member can store data at the given instance. Syntax of Un 5 min read
- Bit Fields in C In C, we can specify the size (in bits) of the structure and union members. The idea of bit-field is to use memory efficiently when we know that the value of a field or group of fields will never exceed a limit or is within a small range. C Bit fields are used when the storage of our program is limi 8 min read
- Difference Between Structure and Union in C Structures in C is a user-defined data type available in C that allows to combining of data items of different kinds. Structures are used to represent a record. Defining a structure: To define a structure, you must use the struct statement. The struct statement defines a new data type, with more tha 4 min read
- Anonymous Union and Structure in C In C11 standard of C, anonymous Unions and structures were added. Anonymous unions/structures are also known as unnamed unions/structures as they don't have names. Since there is no names, direct objects(or variables) of them are not created and we use them in nested structure or unions. Definition 2 min read
- Enumeration (or enum) in C Enumeration (or enum) is a user defined data type in C. It is mainly used to assign names to integral constants, the names make a program easy to read and maintain. enum State {Working = 1, Failed = 0}; The keyword 'enum' is used to declare new enumeration types in C and C++. Enums in C allow you to 4 min read
C Storage Classes
- Storage Classes in C C Storage Classes are used to describe the features of a variable/function. These features basically include the scope, visibility, and lifetime which help us to trace the existence of a particular variable during the runtime of a program. C language uses 4 storage classes, namely: Storage classes i 7 min read
- extern Keyword in C extern keyword in C applies to C variables (data objects) and C functions. Basically, the extern keyword extends the visibility of the C variables and C functions. That's probably the reason why it was named extern. Though most people probably understand the difference between the "declaration" and 7 min read
- Static Variables in C Static variables have the property of preserving their value even after they are out of their scope! Hence, a static variable preserves its previous value in its previous scope and is not initialized again in the new scope. Syntax: static data_type var_name = var_value;Static variables in C retain t 4 min read
- Initialization of static variables in C In C, static variables can only be initialized using constant literals. For example, following program fails in compilation. [GFGTABS] C #include<stdio.h> int initializer(void) { return 50; } int main() { static int i = initializer(); printf(" value of i = %d", i); getchar(); return 1 min read
- Static functions in C In C, functions are global by default. The “static” keyword before a function name makes it static. For example, the below function fun() is static. [GFGTABS] C static int fun(void) { printf("I am a static function "); } [/GFGTABS]Unlike global functions in C, access to static functions is 2 min read
- Understanding "volatile" qualifier in C | Set 2 (Examples) The volatile keyword is intended to prevent the compiler from applying any optimizations on objects that can change in ways that cannot be determined by the compiler. Objects declared as volatile are omitted from optimization because their values can be changed by code outside the scope of current c 6 min read
- Understanding "register" keyword in C Registers are faster than memory to access, so the variables which are most frequently used in a C program can be put in registers using the register keyword. The keyword register hints to the compiler that a given variable can be put in a register. It's the compiler's choice to put it in a register 3 min read
C Memory Management
- Memory Layout of C Programs A typical memory representation of a C program consists of the following sections. Text segment (i.e. instructions)Initialized data segment Uninitialized data segment (bss)Heap Stack A typical memory layout of a running process 1. Text Segment: A text segment, also known as a code segment or simply 6 min read
- Dynamic Memory Allocation in C using malloc(), calloc(), free() and realloc() Since C is a structured language, it has some fixed rules for programming. One of them includes changing the size of an array. An array is a collection of items stored at contiguous memory locations. As can be seen, the length (size) of the array above is 9. But what if there is a requirement to cha 9 min read
- Difference Between malloc() and calloc() with Examples The functions malloc() and calloc() are library functions that allocate memory dynamically. Dynamic means the memory is allocated during runtime (execution of the program) from the heap segment. Initializationmalloc() allocates a memory block of given size (in bytes) and returns a pointer to the beg 3 min read
- What is Memory Leak? How can we avoid? A memory leak occurs when programmers create a memory in a heap and forget to delete it. The consequence of the memory leak is that it reduces the performance of the computer by reducing the amount of available memory. Eventually, in the worst case, too much of the available memory may become alloca 3 min read
- Dynamic Array in C Array in C is static in nature, so its size should be known at compile time and we can't change the size of the array after its declaration. Due to this, we may encounter situations where our array doesn't have enough space left for required elements or we allotted more than the required memory lead 9 min read
- How to dynamically allocate a 2D array in C? Following are different ways to create a 2D array on the heap (or dynamically allocate a 2D array).In the following examples, we have considered 'r' as number of rows, 'c' as number of columns and we created a 2D array with r = 3, c = 4 and the following values 1 2 3 4 5 6 7 8 9 10 11 12 1) Using a 5 min read
- Dynamically Growing Array in C Prerequisite: Dynamic Memory Allocation in C A Dynamically Growing Array is a type of dynamic array, which can automatically grow in size to store data. The C language only has static arrays whose size should be known at compile time and cannot be changed after declaration. This leads to problems li 7 min read
C Preprocessor
- C Preprocessors Preprocessors are programs that process the source code before compilation. Several steps are involved between writing a program and executing a program in C. Let us have a look at these steps before we actually start learning about Preprocessors. You can see the intermediate steps in the above diag 10 min read
- C Preprocessor Directives In almost every C program we come across, we see a few lines at the top of the program preceded by a hash (#) sign. They are called preprocessor directives and are preprocessed by the preprocessor before actual compilation begins. The end of these lines is identified by the newline character '\n', n 8 min read
- How a Preprocessor works in C? Compiling a C program - Behind the Scene A Preprocessor is a system software (a computer program that is designed to run on computer's hardware and application programs). It performs preprocessing of the High Level Language(HLL). Preprocessing is the first step of the language processing system. Lan 3 min read
- Header Files in C In C language, header files contain a set of predefined standard library functions. The .h is the extension of the header files in C and we request to use a header file in our program by including it with the C preprocessing directive "#include". C Header files offer the features like library functi 7 min read
- What’s difference between header files "stdio.h" and "stdlib.h" ? These are two important header files used in C programming. While “<stdio.h>” is header file for Standard Input Output, “<stdlib.h>” is header file for Standard Library. One easy way to differentiate these two header files is that “<stdio.h>” contains declaration of printf() and sc 2 min read
- How to write your own header file in C? As we all know that files with .h extension are called header files in C. These header files generally contain function declarations which we can be used in our main C program, like for e.g. there is need to include stdio.h in our C program to use function printf() in the program. So the question ar 4 min read
- Macros and its types in C In C, a macro is a piece of code in a program that is replaced by the value of the macro. Macro is defined by #define directive. Whenever a macro name is encountered by the compiler, it replaces the name with the definition of the macro. Macro definitions need not be terminated by a semi-colon(;). E 6 min read
- Interesting Facts about Macros and Preprocessors in C In a C program, all lines that start with # are processed by preprocessor which is a special program invoked by the compiler. by this we mean to say that the ‘#’ symbol is used to process the functionality prior than other statements in the program, that is, which means it processes some code before 6 min read
- # and ## Operators in C Stringizing operator (#)The stringizing operator (#) is a preprocessor operator that causes the corresponding actual argument to be enclosed in double quotation marks. The # operator, which is generally called the stringize operator, turns the argument it precedes into a quoted string. It is also kn 2 min read
- How to print a variable name in C? How to print and store a variable name in string variable? We strongly recommend you to minimize your browser and try this yourself first In C, there’s a # directive, also called ‘Stringizing Operator’, which does this magic. Basically # directive converts its argument in a string. #include <stdi 1 min read
- Multiline macros in C In this article, we will discuss how to write a multi-line macro. We can write multi-line macro same like function, but each statement ends with "\". Let us see with example. Below is simple macro, which accepts input number from user, and prints whether entered number is even or odd. #include <s 3 min read
- Variable length arguments for Macros Like functions, we can also pass variable length arguments to macros. For this we will use the following preprocessor identifiers.To support variable length arguments in macro, we must include ellipses (...) in macro definition. There is also "__VA_ARGS__" preprocessing identifier which takes care o 2 min read
- Branch prediction macros in GCC One of the most used optimization techniques in the Linux kernel is " __builtin_expect". When working with conditional code (if-else statements), we often know which branch is true and which is not. If compiler knows this information in advance, it can generate most optimized code. Let us see macro 2 min read
- typedef versus #define in C typedef: The typedef is used to give data type a new name. For example, // C program to demonstrate typedef #include <stdio.h> // After this line BYTE can be used // in place of unsigned char typedef unsigned char BYTE; int main() { BYTE b1, b2; b1 = 'c'; printf("%c ", b1); return 0; 3 min read
- Difference between #define and const in C? #define is a preprocessor directive. Data defined by the #define macro definition are preprocessed, so that your entire code can use it. This can free up space and increase compilation times.const variables are considered variables, and not macro definitions. Long story short: CONSTs are handled by 2 min read
- Basics of File Handling in C File handling in C is the process in which we create, open, read, write, and close operations on a file. C language provides different functions such as fopen(), fwrite(), fread(), fseek(), fprintf(), etc. to perform input, output, and many different C file operations in our program. Why do we need 15 min read
- C fopen() function with Examples The fopen() method in C is a library function that is used to open a file to perform various operations which include reading, writing, etc. along with various modes. If the file exists then the fopen() function opens the particular file else a new file is created. SyntaxThe syntax of C fopen() is: 5 min read
- EOF, getc() and feof() in C In C/C++, getc() returns the End of File (EOF) when the end of the file is reached. getc() also returns EOF when it fails. So, only comparing the value returned by getc() with EOF is not sufficient to check for the actual end of the file. To solve this problem, C provides feof() which returns a non- 3 min read
- fgets() and gets() in C language For reading a string value with spaces, we can use either gets() or fgets() in C programming language. Here, we will see what is the difference between gets() and fgets(). fgets()The fgets() reads a line from the specified stream and stores it into the string pointed to by str. It stops when either 3 min read
- fseek() vs rewind() in C fseek() and rewind() both functions are used to file positioning defined in <stdio.h> header file. In this article, we will discuss the differences in the usage and behavior of both functions. fseek() Function fseek() is used to set the file position indicator to a specified offset from the sp 3 min read
- What is return type of getchar(), fgetc() and getc() ? In C, return type of getchar(), fgetc() and getc() is int (not char). So it is recommended to assign the returned values of these functions to an integer type variable. char ch; /* May cause problems */ while ((ch = getchar()) != EOF) { putchar(ch); } Here is a version that uses integer to compare t 1 min read
- Read/Write Structure From/to a File in C For writing in the file, it is easy to write string or int to file using fprintf and putc, but you might have faced difficulty when writing contents of the struct. fwrite and fread make tasks easier when you want to write and read blocks of data. Writing Structure to a File using fwriteWe can use fw 3 min read
- C Program to print contents of file In C, reading the contents of a file involves opening the file, reading its data, and then processing or displaying the data. Example Input: File containing “This is a test file.\nIt has multiple lines.” Output: This is a test file.It has multiple lines. Explanation: The program reads and displays t 7 min read
- C program to delete a file The remove() function in C/C++ can be used to delete a file. The function returns 0 if the file is deleted successfully, Otherwise, it returns a non-zero value. The remove() is defined inside the <stdio.h> header file. Syntax of remove()remove("filename");ParametersThis function takes a string 2 min read
- C Program to merge contents of two files into a third file Let the given two files be file1.txt and file2.txt. The following are steps to merge. 1) Open file1.txt and file2.txt in read mode. 2) Open file3.txt in write mode. 3) Run a loop to one by one copy characters of file1.txt to file3.txt. 4) Run a loop to one by one copy characters of file2.txt to file 2 min read
- What is the difference between printf, sprintf and fprintf? printf: printf function is used to print character stream of data on stdout console. Syntax : printf(const char* str, ...); Example : C/C++ Code // simple print on stdout #include <stdio.h> int main() { printf("hello geeksquiz"); return 0; } Outputhello geeksquiz sprintf: String prin 2 min read
- Difference between getc(), getchar(), getch() and getche() All of these functions read a character from input and return an integer value. The integer is returned to accommodate a special value used to indicate failure. The value EOF is generally used for this purpose. getc() It reads a single character from a given input stream and returns the correspondin 2 min read
Miscellaneous
- time.h header file in C with Examples The time.h header file contains definitions of functions to get and manipulate date and time information. It describes three time-related data types. clock_t: clock_t represents the date as an integer which is a part of the calendar time. time_t: time_t represents the clock time as an integer which 4 min read
- Input-output system calls in C | Create, Open, Close, Read, Write System calls are the calls that a program makes to the system kernel to provide the services to which the program does not have direct access. For example, providing access to input and output devices such as monitors and keyboards. We can use various functions provided in the C Programming language 10 min read
- Signals in C language Prerequisite : Fork system call, Wait system call A signal is a software generated interrupt that is sent to a process by the OS because of when user press ctrl-c or another process tell something to this process. There are fix set of signals that can be sent to a process. signal are identified by i 5 min read
- Program error signals Signals in computers are a way of communication between the process and the OS. When a running program undergoes some serious error then the OS sends a signal to the process and the process further may not execute. Some processes may have a signal handler that does some important tasks before the pr 3 min read
- Socket Programming in C What is Socket Programming?Socket programming is a way of connecting two nodes on a network to communicate with each other. One socket(node) listens on a particular port at an IP, while the other socket reaches out to the other to form a connection. The server forms the listener socket while the cli 5 min read
- _Generics Keyword in C The _Generic keyword in C is used to implement a generic code that can execute statements based on the type of arguments provided. It can be implemented with C macros to imitate function overloading. The _Generic keyword was first introduced in C11 Standard. Syntax of _Generic in C_Generic( (express 3 min read
- Multithreading in C What is a Thread? A thread is a single sequence stream within a process. Because threads have some of the properties of processes, they are sometimes called lightweight processes. What are the differences between process and thread? Threads are not independent from each other unlike processes. As a 4 min read
- C Programming Interview Questions (2024) At Bell Labs, Dennis Ritchie developed the C programming language between 1971 and 1973. C is a mid-level structured-oriented programming and general-purpose programming. It is one of the oldest and most popular programming languages. There are many applications in which C programming language is us 15+ min read
- Commonly Asked C Programming Interview Questions | Set 1 What is the difference between declaration and definition of a variable/function Ans: Declaration of a variable/function simply declares that the variable/function exists somewhere in the program but the memory is not allocated for them. But the declaration of a variable/function serves an important 5 min read
- Commonly Asked C Programming Interview Questions | Set 2 This post is second set of Commonly Asked C Programming Interview Questions | Set 1What are main characteristics of C language? C is a procedural language. The main features of C language include low-level access to memory, simple set of keywords, and clean style. These features make it suitable for 3 min read
- Commonly Asked C Programming Interview Questions | Set 3 Q.1 Write down the smallest executable code? Ans. main is necessary for executing the code. Code is [GFGTABS] C void main() { } [/GFGTABS]Output Q.2 What are entry control and exit control loops? Ans. C support only 2 loops: Entry Control: This loop is categorized in 2 part a. while loop b. for loop 6 min read
- Top 50 C Coding Interview Questions and Answers (2024) C is the most popular programming language developed by Dennis Ritchie at the Bell Laboratories in 1972 to develop the UNIX operating systems. It is a general-purpose and procedural programming language. It is faster than the languages like Java and Python. C is the most used language in top compani 15+ min read
- C-Operators
- cpp-operator
IMAGES
VIDEO
COMMENTS
The basic question is "Do you want conversions to be performed on the left-hand side parameter of an operator?".If yes, use a free function. If no, use a class member. For example, for operator+() for strings, we want conversions to be performed so we can say things like:. string a = "bar"; string b = "foo" + a; where a conversion is performed to turn the char * "foo" into an std::string.
This makes sense to encourage/enforce the rule of 3. However I implemented a user-defined copy constructor without overloading the assignment operator and it seems like the compiler still generates an implicitly-defined assignment operator to allow copy assignment of a class object, contradicting the above from cppreference.
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.
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 ...
In C++, like other functions, assignment operator function is inherited in derived class. For example, in the following program, base class assignment operator function can be accessed using the derived class object. #include<iostream> using namespace std; class A { public: A & operator= (
I know but this is a homework assignment so I have to do it both ways but I can't figure out what I am doing wrong using the function outside of the class. Jan 23, 2015 at 6:52pm UTC mutexe (2372)
The assignment operator is used to change an existing instance to have the same values as the rvalue, which means that the instance has to be destroyed and re-initialized if it has internal dynamic memory. Useful link : Copy Constructors, Assignment Operators, and More; Copy constructor and = operator overload in C++: is a common function possible?
the copy assignment operator selected for every direct base of T is trivial; the copy assignment operator selected for every non-static class type (or array of class type) member of T is trivial. A trivial copy assignment operator makes a copy of the object representation as if by std::memmove. All data types compatible with the C language (POD ...
Some operators must be overloaded as member functions of the class. Let's discover the intriguing world of operator overloading in C++. We explore how certain operators, like the assignment, subscript, and function call operators, must be overloaded as member functions, making them integral to class objects. We'll also discuss the flexibility of the function call operator and its varied uses.
1. "=": This is the simplest assignment operator. This operator is used to assign the value on the right to the variable on the left. Example: a = 10; b = 20; ch = 'y'; 2. "+=": This operator is combination of '+' and '=' operators.This operator first adds the current value of the variable on left to the value on the right and then assigns the result to the variable on the left.