- Stack Overflow Public questions & answers
- Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
- Talent Build your employer brand
- Advertising Reach developers & technologists worldwide
- About the company

Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
The copy constructor and assignment operator
If I override operator= will the copy constructor automatically use the new operator? Similarly, if I define a copy constructor, will operator= automatically 'inherit' the behavior from the copy constructor?
- constructor
- copy-constructor
- assignment-operator
- Look at the this links : stackoverflow.com/questions/1457842/… & stackoverflow.com/questions/1477145/… – Saurabh Gokhale Mar 20, 2011 at 11:53
- possible duplicate of What is The Rule of Three? – fredoverflow Mar 20, 2011 at 12:25
6 Answers 6
No, they are different operators.
The copy constructor is for creating a new object. It copies an existing object to a newly constructed object.The copy constructor is used to initialize a new instance from an old instance. It is not necessarily called when passing variables by value into functions or as return values out of functions.
The assignment operator is to deal with an already existing object. 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?
- @Prasoon, I don't quite understand, when passing variables by value into functions or as return values out of functions, why copy-constructor might not be called? And what's RVO? – Alcott Sep 12, 2011 at 13:37
- @Alcottreturn value optimization – Ghita Nov 16, 2012 at 6:07
- There is also copy elision, which does the same for function parameters – jupp0r Jan 27, 2016 at 14:02
No. Unless you define a copy ctor, a default will be generated (if needed). Unless you define an operator=, a default will be generated (if needed). They do not use each other, and you can change them independently.
No. They are different objects.
If your concern is code duplication between copy constructor and assignment operator, consider the following idiom, named copy and swap :
This way, the operator= will use the copy constructor to build a new object, which will get exchanged with *this and released (with the old this inside) at function exit.
- by referring to the copy-and-swap idiom, do you imply that it's not a good practice to call operator= in copy-ctor or vice versa? – Alcott Sep 12, 2011 at 13:33
- @Alcott: You don't call the operator= in the copy constructor, you do it the other way around, like I show. – Alexandre C. Sep 12, 2011 at 17:56
- Why is your assignment operator not taking a const reference ? – Johan Boulé May 8, 2016 at 1:48
- @JohanBoule: This is explained in the wikipedia link in my answer, and also in this question – Alexandre C. May 8, 2016 at 7:49
And definitely have a look at the rule of three (or rule of five when taking rvalues into account)
Consider the following C++ program. Note : My "Vector" class not the one from the standard library. My "Vector" class interface :
My "Vector" class members implementation :
Then, the program output:
To wrap up :
- Vector v2 = v1; lead to call copy constructor.
- v3 = v2; lead to call copy assignment operator.
In case 2, Object v3 already exists (We have done: Vector v3{10}; ). There are two obvious differences between copy constructor and copy assignment operator.
- copy constructor NO NEED to delete old elements, it just copy construct a new object. (as it Vector v2 )
- copy constructor NO NEED to return the this pointer.(Furthermore, all the constructor does not return a value).

No, they are not the same operator.

Your Answer
Sign up or log in, post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service , privacy policy and cookie policy
Not the answer you're looking for? Browse other questions tagged c++ constructor operators copy-constructor assignment-operator or ask your own question .
- Featured on Meta
- We've added a "Necessary cookies only" option to the cookie consent popup
- Launching the CI/CD and R Collectives and community editing features for...
- The [amazon] tag is being burninated
- Temporary policy: ChatGPT is banned
- Staging Ground Beta 1 Recap, and Reviewers needed for Beta 2
Hot Network Questions
- How can this new ban on drag possibly be considered constitutional?
- What video game is Charlie playing in Poker Face S01E07?
- Does Counterspell prevent from any further spells being cast on a given turn?
- How do I align things in the following tabular environment?
- Linear regulator thermal information missing in datasheet
- Is it possible to create a concave light?
- Using Kolmogorov complexity to measure difficulty of problems?
- Why did Ukraine abstain from the UNHRC vote on China?
- Can Martian regolith be easily melted with microwaves?
- Disconnect between goals and daily tasks...Is it me, or the industry?
- Why do academics stay as adjuncts for years rather than move around?
- Acidity of alcohols and basicity of amines
- Difficulties with estimation of epsilon-delta limit proof
- Is a PhD visitor considered as a visiting scholar?
- OK to delete Windows.db file on PC?
- Why are Suriname, Belize, and Guinea-Bissau classified as "Small Island Developing States"?
- Minimising the environmental effects of my dyson brain
- Identify those arcade games from a 1983 Brazilian music video
- In Dungeon World, is the Bard's Arcane Art subject to the same failure outcomes as other spells?
- Largest Binary Area
- Edges of each colour for Ramsey Graphs
- What sort of strategies would a medieval military use against a fantasy giant?
- Knocking Out Zombies
- Rolling cube on an infinite chessboard
Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy .
- Graphics and multimedia
- Language Features
- Unix/Linux programming
- Source Code
- Standard Library
- Tips and Tricks
- Tools and Libraries
- Windows API
- Copy constructors, assignment operators,
Copy constructors, assignment operators, and exception safe assignment

cppreference.com
The rule of three/five/zero, [ edit ] rule of three.
If a class requires a user-defined destructor , a user-defined copy constructor , or a user-defined copy assignment operator , it almost certainly requires all three.
Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special member functions will be called, if accessible, and if they are not user-defined, they are implicitly-defined by the compiler.
The implicitly-defined special member functions are typically incorrect if the class manages a resource whose handle is an object of non-class type (raw pointer, POSIX file descriptor, etc), whose destructor does nothing and copy constructor/assignment operator performs a "shallow copy" (copy the value of the handle, without duplicating the underlying resource).
Classes that manage non-copyable resources through copyable handles may have to declare copy assignment and copy constructor private and not provide their definitions or define them as deleted. This is another application of the rule of three: deleting one and leaving the other to be implicitly-defined will most likely result in errors.
[ edit ] Rule of five
Because the presence of a user-defined (or = default or = delete declared) destructor, copy-constructor, or copy-assignment operator prevents implicit definition of the move constructor and the move assignment operator , any class for which move semantics are desirable, has to declare all five special member functions:
Unlike Rule of Three, failing to provide move constructor and move assignment is usually not an error, but a missed optimization opportunity.
[ edit ] Rule of zero
Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership (which follows from the Single Responsibility Principle ). Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators [1] .
This rule also appears in the C++ Core Guidelines as C.20: If you can avoid defining default operations, do .
When a base class is intended for polymorphic use, its destructor may have to be declared public and virtual. This blocks implicit moves (and deprecates implicit copies), and so the special member functions have to be declared as defaulted [2] .
however, this makes the class prone to slicing, which is why polymorphic classes often define copy as deleted (see C.67: A polymorphic class should suppress public copy/move in C++ Core Guidelines), which leads to the following generic wording for the Rule of Five:
[ edit ] External links
- 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 4 February 2023, at 12:58.
- This page has been accessed 623,125 times.
- Privacy policy
- About cppreference.com
- Disclaimers

- Data Structure & Algorithm Classes (Live)
- System Design (Live)
- DevOps(Live)
- Explore More Live Courses
- Interview Preparation Course
- Data Science (Live)
- GATE CS & IT 2024
- Data Structure & Algorithm-Self Paced(C++/JAVA)
- Data Structures & Algorithms in Python
- Explore More Self-Paced Courses
- C++ Programming - Beginner to Advanced
- Java Programming - Beginner to Advanced
- C Programming - Beginner to Advanced
- Android App Development with Kotlin(Live)
- Full Stack Development with React & Node JS(Live)
- Java Backend Development(Live)
- React JS (Basic to Advanced)
- JavaScript Foundation
- Complete Data Science Program(Live)
- Mastering Data Analytics
- CBSE Class 12 Computer Science
- School Guide
- All Courses
- Linked List
- Binary Tree
- Binary Search Tree
- Advanced Data Structure
- All Data Structures
- Asymptotic Analysis
- Worst, Average and Best Cases
- Asymptotic Notations
- Little o and little omega notations
- Lower and Upper Bound Theory
- Analysis of Loops
- Solving Recurrences
- Amortized Analysis
- What does 'Space Complexity' mean ?
- Pseudo-polynomial Algorithms
- Polynomial Time Approximation Scheme
- A Time Complexity Question
- Searching Algorithms
- Sorting Algorithms
- Graph Algorithms
- Pattern Searching
- Geometric Algorithms
- Mathematical
- Bitwise Algorithms
- Randomized Algorithms
- Greedy Algorithms
- Dynamic Programming
- Divide and Conquer
- Backtracking
- Branch and Bound
- All Algorithms
- Company Preparation
- Practice Company Questions
- Interview Experiences
- Experienced Interviews
- Internship Interviews
- Competitive Programming
- Design Patterns
- System Design Tutorial
- Multiple Choice Quizzes
- Go Language
- Tailwind CSS
- Foundation CSS
- Materialize CSS
- Semantic UI
- Angular PrimeNG
- Angular ngx Bootstrap
- jQuery Mobile
- jQuery EasyUI
- React Bootstrap
- React Rebass
- React Desktop
- React Suite
- ReactJS Evergreen
- ReactJS Reactstrap
- BlueprintJS
- TensorFlow.js
- English Grammar
- School Programming
- Number System
- Trigonometry
- Probability
- Mensuration
- Class 8 Syllabus
- Class 9 Syllabus
- Class 10 Syllabus
- Class 8 Notes
- Class 9 Notes
- Class 10 Notes
- Class 11 Notes
- Class 12 Notes
- Class 8 Maths Solution
- Class 9 Maths Solution
- Class 10 Maths Solution
- Class 11 Maths Solution
- Class 12 Maths Solution
- Class 7 Notes
- History Class 7
- History Class 8
- History Class 9
- Geo. Class 7
- Geo. Class 8
- Geo. Class 9
- Civics Class 7
- Civics Class 8
- Business Studies (Class 11th)
- Microeconomics (Class 11th)
- Statistics for Economics (Class 11th)
- Business Studies (Class 12th)
- Accountancy (Class 12th)
- Macroeconomics (Class 12th)
- Machine Learning
- Data Science
- Mathematics
- Operating System
- Computer Networks
- Computer Organization and Architecture
- Theory of Computation
- Compiler Design
- Digital Logic
- Software Engineering
- GATE 2024 Live Course
- GATE Computer Science Notes
- Last Minute Notes
- GATE CS Solved Papers
- GATE CS Original Papers and Official Keys
- GATE CS 2023 Syllabus
- Important Topics for GATE CS
- GATE 2023 Important Dates
- Software Design Patterns
- HTML Cheat Sheet
- CSS Cheat Sheet
- Bootstrap Cheat Sheet
- JS Cheat Sheet
- jQuery Cheat Sheet
- Angular Cheat Sheet
- Facebook SDE Sheet
- Amazon SDE Sheet
- Apple SDE Sheet
- Netflix SDE Sheet
- Google SDE Sheet
- Wipro Coding Sheet
- Infosys Coding Sheet
- TCS Coding Sheet
- Cognizant Coding Sheet
- HCL Coding Sheet
- FAANG Coding Sheet
- Love Babbar Sheet
- Mass Recruiter Sheet
- Product-Based Coding Sheet
- Company-Wise Preparation Sheet
- Array Sheet
- String Sheet
- Graph Sheet
- ISRO CS Original Papers and Official Keys
- ISRO CS Solved Papers
- ISRO CS Syllabus for Scientist/Engineer Exam
- UGC NET CS Notes Paper II
- UGC NET CS Notes Paper III
- UGC NET CS Solved Papers
- Campus Ambassador Program
- School Ambassador Program
- Geek of the Month
- Campus Geek of the Month
- Placement Course
- Testimonials
- Student Chapter
- Geek on the Top
- Geography Notes
- History Notes
- Science & Tech. Notes
- Ethics Notes
- Polity Notes
- Economics Notes
- UPSC Previous Year Papers
- SSC CGL Syllabus
- General Studies
- Subjectwise Practice Papers
- Previous Year Papers
- SBI Clerk Syllabus
- General Awareness
- Quantitative Aptitude
- Reasoning Ability
- SBI Clerk Practice Papers
- SBI PO Syllabus
- SBI PO Practice Papers
- IBPS PO 2022 Syllabus
- English Notes
- Reasoning Notes
- Mock Question Papers
- IBPS Clerk Syllabus
- Apply for a Job
- Apply through Jobathon
- Hire through Jobathon
- All DSA Problems
- Problem of the Day
- GFG SDE Sheet
- Top 50 Array Problems
- Top 50 String Problems
- Top 50 Tree Problems
- Top 50 Graph Problems
- Top 50 DP Problems
- Solving For India-Hackthon
- GFG Weekly Coding Contest
- Job-A-Thon: Hiring Challenge
- BiWizard School Contest
- All Contests and Events
- Saved Videos
- What's New ?
- Data Structures
- Interview Preparation
- Topic-wise Practice
- Latest Blogs
- Write & Earn
- Web Development
Related Articles
- Write Articles
- Pick Topics to write
- Guidelines to Write
- Get Technical Writing Internship
- Write an Interview Experience
- Vector in C++ STL
- Arrays in C/C++
- Initialize a vector in C++ (7 different ways)
- Map in C++ Standard Template Library (STL)
- std::sort() in C++ STL
- Bitwise Operators in C/C++
- The C++ Standard Template Library (STL)
- Inheritance in C++
- Object Oriented Programming in C++
- C++ Classes and Objects
- Multidimensional Arrays in C / C++
- Virtual Function in C++
- Set in C++ Standard Template Library (STL)
- Constructors in C++
- vector erase() and clear() in C++
- C++ Data Types
- Left Shift and Right Shift Operators in C/C++
- Substring in C++
- Converting Strings to Numbers in C/C++
- unordered_map in C++ STL
- Templates in C++ with Examples
- Socket Programming in C/C++
- Operator Overloading in C++
- Copy Constructor in C++
- rand() and srand() in C++
- 2D Vector In C++ With User Defined Size
- Stack in C++ STL
- getline (string) in C++
- Priority Queue in C++ Standard Template Library (STL)
- Sorting a vector in C++
C++ Assignment Operator Overloading
- Difficulty Level : Medium
- Last Updated : 27 Oct, 2022
Prerequisite: Operator Overloading
The assignment operator,”=”, is the operator used for Assignment. It copies the right value into the left value. Assignment Operators are predefined to operate only on built-in Data types.
- Assignment operator overloading is binary operator overloading.
- Overloading assignment operator in C++ copies all values of one object to another object.
- Only a non-static member function should be used to overload the assignment operator.
We can’t directly use the Assignment Operator on objects. The simple explanation for this is that the Assignment Operator is predefined to operate only on built-in Data types. As the class and objects are user-defined data types, so the compiler generates an error.
here, a and b are of type integer, which is a built-in data type. Assignment Operator can be used directly on built-in data types.
c1 and c2 are variables of type “class C”. Here compiler will generate an error as we are trying to use an Assignment Operator on user-defined data types.
The above example can be done by implementing methods or functions inside the class, but we choose operator overloading instead. The reason for this is, operator overloading gives the functionality to use the operator directly which makes code easy to understand, and even code size decreases because of it. Also, operator overloading does not affect the normal working of the operator but provides extra functionality to it.
Now, if the user wants to use the assignment operator “=” to assign the value of the class variable to another class variable then the user has to redefine the meaning of the assignment operator “=”. Redefining the meaning of operators really does not change their original meaning, instead, they have been given additional meaning along with their existing ones.
Please Login to comment...
- cpp-operator
- cpp-operator-overloading
Improve your Coding Skills with Practice
Start your coding journey now.
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
Copy constructors and copy assignment operators (C++)
- 2 minutes to read
- 9 contributors
Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment . In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++) .
Both the assignment operation and the initialization operation cause objects to be copied.
Assignment : When one object's value is assigned to another object, the first object is copied to the second object. So, this code copies the value of b into a :
Initialization : Initialization occurs when you declare a new object, when you pass function arguments by value, or when you return by value from a function.
You can define the semantics of "copy" for objects of class type. For example, consider this code:
The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make b a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows:
Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator=(const ClassName& x); .
Use the copy constructor.
If you don't declare a copy constructor, the compiler generates a member-wise copy constructor for you. Similarly, if you don't declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor doesn't suppress the compiler-generated copy assignment operator, and vice-versa. If you implement either one, we recommend that you implement the other one, too. When you implement both, the meaning of the code is clear.
The copy constructor takes an argument of type ClassName& , where ClassName is the name of the class. For example:
Make the type of the copy constructor's argument const ClassName& whenever possible. This prevents the copy constructor from accidentally changing the copied object. It also lets you copy from const objects.
Compiler generated copy constructors
Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name ." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type const class-name & . In such a case, the compiler-generated copy constructor's argument is also const .
When the argument type to the copy constructor isn't const , initialization by copying a const object generates an error. The reverse isn't true: If the argument is const , you can initialize by copying an object that's not const .
Compiler-generated assignment operators follow the same pattern for const . They take a single argument of type ClassName& unless the assignment operators in all base and member classes take arguments of type const ClassName& . In this case, the generated assignment operator for the class takes a const argument.
When virtual base classes are initialized by copy constructors, whether compiler-generated or user-defined, they're initialized only once: at the point when they are constructed.
The implications are similar to the copy constructor. When the argument type isn't const , assignment from a const object generates an error. The reverse isn't true: If a const value is assigned to a value that's not const , the assignment succeeds.
For more information about overloaded assignment operators, see Assignment .
Submit and view feedback for
Additional resources
Tech Differences
Know the Technical Differences
Difference Between Copy Constructor and Assignment Operator in C++

Let us study the difference between the copy constructor and assignment operator.
Content: Copy Constructor Vs Assignment Operator
Comparison chart.
- Key Differences
Definition of Copy Constructor
A “copy constructor” is a form of an overloaded constructor . A copy constructor is only called or invoked for initialization purpose. A copy constructor initializes the newly created object by another existing object.
When a copy constructor is used to initialize the newly created target object, then both the target object and the source object shares a different memory location. Changes done to the source object do not reflect in the target object. The general form of the copy constructor is
If the programmer does not create a copy constructor in a C++ program, then the compiler implicitly provides a copy constructor. An implicit copy constructor provided by the compiler does the member-wise copy of the source object. But, sometimes the member-wise copy is not sufficient, as the object may contain a pointer variable.
Copying a pointer variable means, we copy the address stored in the pointer variable, but we do not want to copy address stored in the pointer variable, instead, we want to copy what pointer points to. Hence, there is a need of explicit ‘copy constructor’ in the program to solve this kind of problems.
A copy constructor is invoked in three conditions as follow:
- Copy constructor invokes when a new object is initialized with an existing one.
- The object passed to a function as a non-reference parameter.
- The object is returned from the function.
Let us understand copy constructor with an example.
In the code above, I had explicitly declared a constructor “copy( copy &c )”. This copy constructor is being called when object B is initialized using object A. Second time it is called when object C is being initialized using object A.
When object D is initialized using object A the copy constructor is not called because when D is being initialized it is already in the existence, not the newly created one. Hence, here the assignment operator is invoked.
Definition of Assignment Operator
The assignment operator is an assigning operator of C++. The “=” operator is used to invoke the assignment operator. It copies the data in one object identically to another object. The assignment operator copies one object to another member-wise. If you do not overload the assignment operator, it performs the bitwise copy. Therefore, you need to overload the assignment operator.
In above code when object A is assigned to object B the assignment operator is being invoked as both the objects are already in existence. Similarly, same is the case when object C is initialized with object A.
When the bitwise assignment is performed both the object shares the same memory location and changes in one object reflect in another object.
Key Differences Between Copy Constructor and Assignment Operator
- A copy constructor is an overloaded constructor whereas an assignment operator is a bitwise operator.
- Using copy constructor you can initialize a new object with an already existing object. On the other hand, an assignment operator copies one object to the other object, both of which are already in existence.
- A copy constructor is initialized whenever a new object is initialized with an already existing object, when an object is passed to a function as a non-reference parameter, or when an object is returned from a function. On the other hand, an assignment operator is invoked only when an object is being assigned to another object.
- When an object is being initialized using copy constructor, the initializing object and the initialized object shares the different memory location. On the other hand, when an object is being initialized using an assignment operator then the initialized and initializing objects share the same memory location.
- If you do not explicitly define a copy constructor then the compiler provides one. On the other hand, if you do not overload an assignment operator then a bitwise copy operation is performed.
The Copy constructor is best for copying one object to another when the object contains raw pointers.
Related Differences:
- Difference Between & and &&
- Difference Between Recursion and Iteration
- Difference Between new and malloc( )
- Difference Between Inheritance and Polymorphism
- Difference Between Constructor and Destructor
Leave a Reply Cancel reply
Your email address will not be published. Required fields are marked *
- Coding Ground
- Corporate Training

- C++ Overview
- C++ Environment Setup
- C++ Basic Syntax
- C++ Comments
- C++ Data Types
- C++ Variable Types
- C++ Variable Scope
- C++ Constants/Literals
- C++ Modifier Types
- C++ Storage Classes
- C++ Operators
- C++ Loop Types
- C++ Decision Making
- C++ Functions
- C++ Numbers
- C++ Strings
- C++ Pointers
- C++ References
- C++ Date & Time
- C++ Basic Input/Output
- C++ Data Structures
- C++ Object Oriented
- C++ Classes & Objects
- C++ Inheritance
- C++ Overloading
- C++ Polymorphism
- C++ Abstraction
- C++ Encapsulation
- C++ Interfaces
- C++ Advanced
- C++ Files and Streams
- C++ Exception Handling
- C++ Dynamic Memory
- C++ Namespaces
- C++ Templates
- C++ Preprocessor
- C++ Signal Handling
- C++ Multithreading
- C++ Web Programming
- C++ Useful Resources
- C++ Questions and Answers
- C++ Quick Guide
- C++ STL Tutorial
- C++ Standard Library
- C++ Discussion
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
Assignment Operators Overloading in C++
You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor.
Following example explains how an assignment operator can be overloaded.
When the above code is compiled and executed, it produces the following result −
14.12 — The copy constructor
C++. Move constructor and move operator
Move constructor and move operator. the purpose. examples. the noexcept keyword. an example of vector class (dynamic array).
Before exploring this topic, it is recommended that you familiarize yourself with the following topic:
- Class constructor. Features of use constructors in the classes. The default constructor. Parameterized constructor. Examples of calsses that contain constructors
1. What special class functions are provided by the compiler by default? Example
2. move constructor and move operator. the purpose. features of use. general form, 3. figure showing the purpose of a move constructor in a class, 4. ways of calling the move constructor. references of type rvalue- and lvalue-. actions performed in the move constructor, 5. move operator. general form, 6.2.1. the components of the vector class, 6.2.2. internal class fields, 6.2.3. internal private functions free() , copyarray(), 6.2.4. constructor with two parameters vector(double*, int), 6.2.5. destructor ~vector(), 6.2.6. parameterless constructor vector(), 6.2.7. copy constructor vector(const vector&), 6.2.8. copy operator operator=(const vector&), 6.2.9. copy constructor vector(vector&&), 6.2.10. move operator operator=(vector&&), 6.2.11. method set(double*, int) . set a new array, 6.2.12. method print(string) . display an array with the given message, 6.2.13. general structure of the vector class, 6.2.14. method getv() . get a random array, 6.2.15. function main(), 6.2.16. general structure of the program, 6.2.17. run the program, related topics.
Search other resources:
When the class is initially declared, the compiler provides 6 special functions by default that can be overridden:
- default constructor or parameterless constructor. Used to create an instance of a class if no other constructors are implemented in the class;
- destructor ;
- copy constructor . Uses bitwise copying of instance data. This constructor must be overridden in classes where memory for data is dynamically allocated. If memory in classes is not dynamically allocated (using pointers *), then this constructor does not need to be redefined;
- copy operator . Uses a bitwise copy of the instance data. This operator must be overridden in classes where memory is dynamically allocated for data. If there is no dynamic memory allocation in the class, then the copy operator need not be overridden;
- move constructor . It is recommended to override this constructor in classes that can contain (or contain) large data arrays, memory for which is dynamically allocated;
- move operator . Has the same purpose as move constructor.
Any of the above functions can be overridden in a class with your own implementation.
Example . Let an empty class (stub) named MyClass be given
For the class MyClass , the compiler generates 6 special functions by default. The signature of these functions is as follows:
- MyClass() – default constructor. This constructor has no parameters. It is relevant when the class does not have a single constructor that initializes the internal fields (data) of the class;
- ~MyClass() – destructor. This is a special function called when a class object is destroyed. In this function, it is advisable to write the code for releasing the allocated class resources (freeing memory for data, closing open files, etc.);
- MyClass(const MyClass&) – copy constructor. This constructor implements what’s called bitwise copying. You can read more about bitwise copying and using the copy constructor here and here ;
- operator(const MyClass&) – copy operator. Implements the so-called bitwise copying. More details about the features of bitwise copying can be found here ;
- MyClass(MyClass&&) – move constructor (described in this topic);
- operator(MyClass&&) – move operator (described in this topic).
The move constructor and the move operator were added in C++ 11. The main idea behind using these two constructs is to speed up program execution by avoiding copying data during initial initialization and assignment of so-called rvalue references.
It is advisable to declare the move constructor and the move operator in classes containing large data arrays. Nobody bothers to declare a move constructor or a move operator in the class in which there are only a few simple fields of small dimension. However, in this case, the effect of using the move constructor will be negligible (or not at all).
Also, if it becomes necessary to use these structures, it is recommended to add them in pairs (both structures).
If the move constructor is not implemented in the class , then its call is replaced by the copy constructor. If the move operator is not implemented in the class, then its call is replaced by the copy operator.
The general form of declaring a move constructor in a class
- ClassName – the name of the class and constructor;
- rObj – reference to a reference to a temporary instance of the class (rvalue – instance), the value of which will be copied to the current instance.
The above general form uses the noexcept keyword. This specifier indicates that our function (the move constructor) does not throw (throw) an exception or crash. The compiler recommends using the word noexcept for the move constructor and the move operator. In the move constructor, no memory operations are performed (memory allocation, memory release, writing data to the allocated memory area, etc.), but a simple assignment of the pointer (s) takes place.
Figure 1 shows the case when the class does not implement the move constructor and the copy constructor is called instead. Copying a large data array A with dimension n elements for a class named MyClass is considered. As you can see from the figure, the entire array is copied element by element. If the number of elements in this array is large, this process will take some time.

Figure 1. Actions performed by the copy constructor. Copying the entire array
After adding the move constructor to the MyClass class, the data is no longer copied (Figure 2). This gives a significant gain in the speed of program execution if the number of elements in the obj.A array is significant (for example, n = 1E6).

Figure 2. Move constructor. Assigning (redirecting) a pointer to the source array. Data is not copied
This topic covers only the general features of rvalue- and lvalue- references. A detailed overview of lvalues and rvalues is a completely different topic that requires a separate thorough study.
If a move constructor is declared in a class, then it is called in cases when the expression that initializes the value of an instance of this class with the = operator receives another instance, which is a so-called rvalue reference.
Below we consider one of the possible situations of calling the move constructor.
In the most general case, any function that returns an instance of the ClassName class looks like this:
The move constructor is called when the SomeFunc() function is called at the time the class instance is declared.
The obj instance is located on the left side of the assignment operator and is an lvalue reference. Such a reference is scoped within curly braces { } and is available after the current expression completes. In other words, you can use the obj instance in the future, for example
here SomeInternalMethod() is some public method from the ClassName class.
In turn, the SumeFunc() function is placed on the right side of the = operator. The result returned by the function is an instance of the ClassName class. In this case, this instance is a temporary rvalue reference. The scope of this temporary object is determined by the current expression. This temporary instance will not be used after the assignment (Figure 3).

Figure 3. The case where the move constructor is called. Scopes for lvalue and rvalue references
If a class implements its own move constructor, such initializations will call that constructor instead of the copy constructor.
If you make a correct assignment from an rvalue to an lvalue reference in the move constructor, you can avoid unnecessary copying of data from the memory area pointed to by the rvalue reference to the area pointed to by the lvalue reference. With an increase in the amount of data in the class (for example, large amounts of information), the effect of using the move constructor will increase.
The following actions are performed in the move constructor:
- internal pointers should be redirected to external data, which should be copied into the internal fields of the class. In other words, internal pointers receive the values of addresses of memory areas containing data received from outside (see example below).
The purpose of using the move operator is the same as that of the move constructor – to speed up program execution by avoiding direct copying of data when assigning so-called rvalue references, which are used in expressions on the right side of the assignment operator.
If a move operator is declared in a class, then it is called in cases when an instance of a class is obtained in the assignment operator ( = ), which is the result of a return from another function.
here SomeFunc() is some function that returns the instance of the class ClassName .
If the class does not implement the move operator, then this operator is replaced by the copy operator.
The general form of declaring a move operator in a class:
- ClassName – the name of the class;
- obj – object that is an rvalue reference in the calling expression.
The move operator has more sequence of actions than the copy constructor, namely:
- checking whether an instance is being assigned to itself in cases where a function can somehow return the same instance (see examples below);
- freeing memory for allocated internal data. The lvalue has already been instantiated and already contains some data;
- assignment of internal pointers to the addresses of the data to be copied into the current instance.
For more details on the implementation of the move operator, see the example below.
6. An example of implementation of the Vector class (dynamic array). Basic set of methods. The move constructor and the move operator in the class
The example demonstrates the declaration and use of the Vector class, which implements a dynamic array of type double* . The class uses a basic set of special class functions and methods for demonstration purposes. These functions ensure the correct functioning of class instances (memory allocation, deallocation, exception handling, etc.). Optionally, you can reprogram this class to a one-dimensional array for the generic type T .
You can also extend the class by adding new methods that operate on an array. For example, you can add methods for reversing an array, concatenating, accessing array elements by index, etc.
Develop a class that is a dynamic array. In the class, form a minimum set of special functions for organizing work with an array.
6.2. Solution
The class contains the following components:
- A – array of double* type;
- count – the number of elements in the array
- Vector(double*, int) – a parameterized constructor that initializes the class data;
- Vector() – constructor without a parameters;
- Vector(const Vector&) – copy constructor;
- Vector(Vector&&) – move constructor;
- operator=(const Vector&) – copy operator;
- operator=(Vector&&) – move operator;
- ~Vector() – destructor;
- Free() – an internal private-function that frees the data allocated for array A ;
- CopyArray() – an internal private function that copies external data into an internal array;
- метод Set() – implements copying of an external array to an internal one;
- метод Print() – prints the array to the screen. Used for testing.
The above list is the basic (minimum) set of functions to ensure the correct functioning of the class. Optionally, this set can be expanded with additional functions.
A dynamic array of elements of type double is declared with double* . The number of elements in the array is count. After entering these variables, the class looks like this
In our case, it is agreed that the check for the presence of an empty array is carried out based on the value of count . If count> 0 , then the array is not empty. In all other cases, the array is considered empty. The control over the filling of the array lies entirely with the count variable.
In different methods of the class, the program code will be repeated. The basic operations commonly used on an array are:
- freeing the memory allocated for the array;
- copying an external array to an internal array A .
Therefore, it is advisable to implement the corresponding internal private-functions Free() and CopyArray() in the class. After entering the functions, the program code of the class is as follows:
The Free() function frees the memory allocated for the array A . This function will be called from other functions in cases when it is necessary to reallocate memory or free memory.
In the Free() function, the fact of the presence of parts in the array is checked by the count variable ( count==0 ). Therefore, in the case of an empty array, you do not need to assign nullptr to the pointer A every time.
When designing classes, a different number of constructors can be used to initialize internal data. The first is the constructor that initializes the array to cover the largest number of internal fields of the class. In our case, the following constructor with two parameters is introduced into the public section:
The constructor uses the internal CopyArray() function to copy data to the internal array A .
After declaring a parameterized constructor, a destructor must be declared that calls the internal function Free() .
Another constructor that can be used to create an empty array is the parameterless constructor. This constructor delegates its authority to the constructor with two parameters. The constructor is introduced in the public section.
This is the only time the program uses nullptr to assign a value to pointer A . In all other cases, you do not need to set pointer A to nullptr , since control over the presence of an empty array is entirely in the variable count .
Since our class uses dynamic memory allocation for internal data, it is imperative to use the copy constructor to avoid the disadvantages of bitwise copying. More details about this are described here and here .
In our case, the copy constructor code is extremely simple. The CopyArray() function is called to do all the necessary work.
The copy operator must be implemented in cases where the class uses dynamic memory allocation. In our case, the copy operator code contains a call to the CopyArray() function.
The transfer constructor code does not perform any memory operations (memory allocation, deallocation, etc.).
In the move constructor, the most important line is
This action is required, because when assigning pointers
we get a situation that both pointers ( A and obj.A ) point to the same memory area. In the case of freeing memory for pointers, the same memory area will be freed twice, and this will result in an exception being thrown. To avoid this, the number of elements in the temporary object obj.count is set to 0. When calling the function Free() , which frees memory, count is checked for a nonzero value; if count == 0 , then the memory is not freed, and, therefore, unnecessary (unnecessary) memory will not be freed.
Since our class has a dynamic array that can have an arbitrary number of elements, it is recommended to declare a move operator in it.
For demonstration purposes, the class implements the Set() method, which makes a copy of the external array, which is an input parameter, into the internal array.
It would be wrong to assign like
since two arrays (external and internal) will point to the same memory location, which in some situations can lead to subtle errors.
To get the current state of the class, the Print() method is introduced.
After completing clauses 4.2.2 – 4.2.13, the Vector class in its abbreviated form will be as follows.
To demonstrate how to call the move constructor and the move operator outside the Vector class, the GetV() function is introduced, which forms an arbitrary array and returns an instance of the Vector type.
The test of the Vector class is done in the main() function.
In the most general case, the program structure has the form
After combining all the above code snippets, running the program will produce the following result
- Copy constructor . Examples of using. Passing a class object to a function. Returning a class object from a function
- Destructor. Definition of the destructor. Public and private destructors. Examples of destructors using. Differences between constructors and destructors
Programming: theory and practice
Operator overloading__CH_14

14.1 — Introduction to operator overloading
Using function overloading to overload operators is called operator overloading .
Operators as functions
Consider the following example:
The compiler comes with a built-in version of the plus operator (+) for integer operands – this function adds integers x and y together and returns an integer result. When you see the expression x + y , you can translate this in your head to the function call operator+(x, y) (where operator+ is the name of the function).
Resolving overloaded operators
What are the limitations on operator overloading, best practice.
When overloading operators, it’s best to keep the function of the operators as close to the original intent of the operators as possible.
If the meaning of an overloaded operator is not clear and intuitive, use a named function instead.
14.2 — Overloading the arithmetic operators using friend functions
Overloading operators using friend functions.
Overloading the subtraction operator (-) is simple as well:
Overloading the multiplication operator ( ) and the division operator (/) is as easy as defining functions for operator and operator/ respectively.
Friend functions can be defined inside the class
Even though friend functions are not members of the class, they can still be defined inside the class if desired:
We generally don’t recommend this, as non-trivial function definitions are better kept in a separate .cpp file, outside of the class definition. However, we will use this pattern in future tutorials to keep the examples concise.
Overloading operators for operands of different types
Consequently, whenever we overload binary operators for operands of different types, we actually need to write two functions – one for each case. Here is an example of that:
Note that both overloaded functions have the same implementation – that’s because they do the same thing, they just take their parameters in a different order.
Another example
In other words, this expression evaluates as “MinMax mFinal = (((((m1 + m2) + 5) + 8) + m3) + 16)”, with each successive operation returning a MinMax object that becomes the left-hand operand for the following operator.
Implementing operators using other operators
In the above example, note that we defined operator+(int, MinMax) by calling operator+(MinMax, int) (which produces the same result). This allows us to reduce the implementation of operator+(int, MinMax) to a single line, making our code easier to maintain by minimizing redundancy and making the function simpler to understand.
It is often possible to define overloaded operators by calling other overloaded operators. You should do so if and when doing so produces simpler code. In cases where the implementation is trivial (e.g. a single line) it may or may not be worth doing this.
14.3 — Overloading operators using normal functions
Prefer overloading operators as normal functions instead of friends if it’s possible to do so without adding additional functions.
14.4 — Overloading the I/O operators
Overloading operator<<.
Overloading operator<< and operator>> make it extremely easy to output your class to screen and accept user input from the console.
Take the Fraction class we wrote in the previous quiz (listed below) and add an overloaded operator<< and operator>> to it.

14.5 — Overloading operators using member functions
So if we can overload an operator as a friend or a member, which should we use? In order to answer that question, there’s a few more things you’ll need to know.
Not everything can be overloaded as a friend function
The assignment (=), subscript ([]), function call (()), and member selection (->) operators must be overloaded as member functions, because the language requires them to be.
Not everything can be overloaded as a member function
When to use a normal, friend, or member function overload.
In most cases, the language leaves it up to you to determine whether you want to use the normal/friend or member function version of the overload. However, one of the two is usually a better choice than the other.
The following rules of thumb can help you determine which form is best for a given situation:
- If you’re overloading assignment (=), subscript ([]), function call (()), or member selection (->), do so as a member function.
- If you’re overloading a unary operator, do so as a member function.
- If you’re overloading a binary operator that does not modify its left operand (e.g. operator+), do so as a normal function (preferred) or friend function.
- If you’re overloading a binary operator that modifies its left operand, but you can’t add members to the class definition of the left operand (e.g. operator<<, which has a left operand of type ostream), do so as a normal function (preferred) or friend function.
- If you’re overloading a binary operator that modifies its left operand (e.g. operator+=), and you can modify the definition of the left operand, do so as a member function.
14.6 — Overloading unary operators +, -, and !
Overloading unary operators.
Implement overloaded operator+ for the Point class. Hide Solution
Here’s the obvious solution:
But because the Point we’re returning is exactly the same one we’re operating on, the following also works:
Note that we’re returning a copy by value rather than a const reference here. This is because users of this function will probably expect the returned object to be modifiable.
The unary minus operator returns the operand multiplied by -1. In other words, if x = 5, -x is -5.
The unary plus operator returns the value of the operand. In other words, +5 is 5, and +x is x. Generally you won’t need to use this operator since it’s redundant. It was added largely to provide symmetry with the unary minus operator.
The following program doesn’t seem to work for me unless I put -f in between parenthesis (-f).print(); Why?
error: expression must have arithmetic or unscoped enum type.
with the first code in this tutorial, I was able to remove the parentheses (line 26 -nickle) and it worked just fine.
Alex: Operator. has higher precedence than operator-, so this evaluates as -(f.print()). Since Fraction::print() returns a void, the compiler will complain about an illegal operand on void.
You need the parenthesis to ensure that -f is evaluated first, and then print() invoked on the result.
14.7 — Overloading the comparison operators
Only define overloaded operators that make intuitive sense for your class.
However, there is one common exception to the above recommendation. What if we wanted to sort a list of Cars? In such a case, we might want to overload the comparison operators to return the member (or members) you’re most likely to want to sort on. For example, an overloaded operator< for Cars might sort based on make and model alphabetically.
Some of the container classes in the standard library (classes that hold sets of other classes) require an overloaded operator< so they can keep the elements sorted.
Here’s a different example overloading all 6 logical comparison operators:
This is also pretty straightforward.
Minimizing comparative redundancy
This way, if we ever need to change something, we only need to update operator== and operator< instead of all six comparison operators!
The spaceship operator <=> C++20
C++20 introduces the spaceship operator (operator<=>), which allows us to reduce the number of comparison functions we need to write down to 2 at most, and sometimes just 1!
Author’s note
We intend to add a new lesson on this topic soon. Until then, consider this something to pique your interest – but you’ll have to go off-site to discover more.
14.8 — Overloading the increment and decrement operators
Overloading prefix increment and decrement.
Prefix increment and decrement are overloaded exactly the same as any normal unary operator. We’ll do this one by example:
Overloading postfix increment and decrement
Normally, functions can be overloaded when they have the same name but a different number and/or different type of parameters. However, consider the case of the prefix and postfix increment and decrement operators. Both have the same name (eg. operator++), are unary, and take one parameter of the same type. So how it is possible to differentiate the two when overloading?
The C++ language specification has a special case that provides the answer: the compiler looks to see if the overloaded operator has an int parameter. If the overloaded operator has an int parameter, the operator is a postfix overload. If the overloaded operator has no parameter, the operator is a prefix overload.
Here is the above Digit class with both prefix and postfix overloads:
This prints
There are a few interesting things going on here. First, note that we’ve distinguished the prefix from the postfix operators by providing an integer dummy parameter on the postfix version. Second, because the dummy parameter is not used in the function implementation, we have not even given it a name. This tells the compiler to treat this variable as a placeholder, which means it won’t warn us that we declared a variable but never used it.
Third, note that the prefix and postfix operators do the same job – they both increment or decrement the object. The difference between the two is in the value they return. The overloaded prefix operators return the object after it has been incremented or decremented. Consequently, overloading these is fairly straightforward. We simply increment or decrement our member variables, and then return *this.
The postfix operators, on the other hand, need to return the state of the object before it is incremented or decremented. This leads to a bit of a conundrum – if we increment or decrement the object, we won’t be able to return the state of the object before it was incremented or decremented. On the other hand, if we return the state of the object before we increment or decrement it, the increment or decrement will never be called.
The typical way this problem is solved is to use a temporary variable that holds the value of the object before it is incremented or decremented. Then the object itself can be incremented or decremented. And finally, the temporary variable is returned to the caller. In this way, the caller receives a copy of the object before it was incremented or decremented, but the object itself is incremented or decremented. Note that this means the return value of the overloaded operator must be a non-reference, because we can’t return a reference to a local variable that will be destroyed when the function exits. Also note that this means the postfix operators are typically less efficient than the prefix operators because of the added overhead of instantiating a temporary variable and returning by value instead of reference.
Finally, note that we’ve written the post-increment and post-decrement in such a way that it calls the pre-increment and pre-decrement to do most of the work. This cuts down on duplicate code, and makes our class easier to modify in the future.
14.9 — Overloading the subscript operator
Overloading operator[].
This is both easy syntactically and from a comprehension standpoint. When list[2] evaluates, the compiler first checks to see if there’s an overloaded operator[] function. If so, it passes the value inside the hard braces (in this case, 2) as an argument to the function.
Note that although you can provide a default value for the function parameter, actually using operator[] without a subscript inside is not considered a valid syntax, so there’s no point.
C++23 will add support for overloading operator[] with multiple subscripts.
Why operator[] returns a reference
Consider what would happen if operator[] returned an integer by value instead of by reference. list[2] would call operator[], which would return the value of list.m_list[2]. For example, if m_list[2] had the value of 6, operator[] would return the value 6. list[2] = 3 would partially evaluate to 6 = 3, which makes no sense! If you try to do this, the C++ compiler will complain:
Dealing with const objects
If we comment out the line clist[2] = 3 , the above program compiles and executes as expected.
Error checking
One other advantage of overloading the subscript operator is that we can make it safer than accessing arrays directly. Normally, when accessing arrays, the subscript operator does not check whether the index is valid. For example, the compiler will not complain about the following code:
However, if we know the size of our array, we can make our overloaded subscript operator check to ensure the index is within bounds:
In the above example, we have used the assert() function (included in the cassert header) to make sure our index is valid. If the expression inside the assert evaluates to false (which means the user passed in an invalid index), the program will terminate with an error message, which is much better than the alternative (corrupting memory). This is probably the most common method of doing error checking of this sort.
Pointers to objects and overloaded operator[] don’t mix
If you try to call operator[] on a pointer to an object, C++ will assume you’re trying to index an array of objects of that type.
Because we can’t assign an integer to an IntList, this won’t compile. However, if assigning an integer was valid, this would compile and run, with undefined results.
Make sure you’re not trying to call an overloaded operator[] on a pointer to an object.
The proper syntax would be to dereference the pointer first (making sure to use parenthesis since operator[] has higher precedence than operator*), then call operator[]:
This is ugly and error prone. Better yet, don’t set pointers to your objects if you don’t have to.
The function parameter does not need to be an integer
As mentioned above, C++ passes what the user types between the hard braces as an argument to the overloaded function. In most cases, this will be an integer value. However, this is not required – and in fact, you can define that your overloaded operator[] take a value of any type you desire. You could define your overloaded operator[] to take a double, a std::string, or whatever else you like.
As a ridiculous example, just so you can see that it works:
As you would expect, this prints:
Overloading operator[] to take a std::string parameter can be useful when writing certain kinds of classes, such as those that use words as indices.
The subscript operator is typically overloaded to provide direct access to individual elements from an array (or other similar structure) contained within a class. Because strings are often implemented as arrays of characters, operator[] is often implemented in string classes to allow the user to access a single character of the string.
Question #1
Since maps are common, the standard library offers std::map, which is not currently covered on learncpp. Using std::map, we can simplify our code to
Prefer using std::map over writing your own implementation.
Question #3
Extra credit #2: Why does this program potentially not work as expected?
Hide Solution
When Frank is added, the std::vector may need to grow to hold it. This requires dynamically allocating a new block of memory, copying the elements in the array to that new block, and deleting the old block. When this happens, any references to existing elements in the std::vector are invalidated (meaning they are left as dangling references to deleted memory).
In other words, after we push_back(“Frank”), if the std::vector had to grow to make room for Frank, the gradeJoe reference would be invalidated. Accessing gradeJoe to print Joe’s grade would then lead to undefined results.
How a std::vector grows is a compiler-specific detail, so we can expect the above program to work fine when compiled with some compilers and not others.
14.10 — Overloading the parenthesis operator
Now, let’s overload the () operator again, this time in a way that takes no parameters at all:
And here’s our new example:
which produces the result:
Because the () operator is so flexible, it can be tempting to use it for many different purposes. However, this is strongly discouraged, since the () symbol does not really give any indication of what the operator is doing. In our example above, it would be better to have written the erase functionality as a function called clear() or erase(), as matrix.erase() is easier to understand than matrix() (which could do anything!).
Having fun with functors
Operator() is also commonly overloaded to implement functors (or function object ), which are classes that operate like functions. The advantage of a functor over a normal function is that functors can store data in member variables (since they are classes).
Here’s a simple functor:
Note that using our Accumulator looks just like making a normal function call, but our Accumulator object is storing an accumulated value.
You may wonder why we couldn’t do the same thing with a normal function and a static local variable to preserve data between function calls. We could, but because functions only have one global instance, we’d be limited to using it for one thing at a time. With functors, we can instantiate as many separate functor objects as we need and use them all simultaneously.
Operator() is sometimes overloaded with two parameters to index multidimensional arrays, or to retrieve a subset of a one dimensional array (with the two parameters defining the subset to return). Anything else is probably better written as a member function with a more descriptive name.
Operator() is also often overloaded to create functors. Although simple functors (such as the example above) are fairly easily understood, functors are typically used in more advanced programming topics, and deserve their own lesson.
Extra credit: Implement a member function named substr that returns the same substring as a std::string_view.
Let’s explore return std::string_view{ m_string }.substr(start, length); further. First, we’re creating a temporary std::string_view of m_string , which is inexpensive and lets us access std::string_view member functions. Next, we call std::string_view::substr on this temporary to get our substring (as a non-null-terminated view of m_string ). We then return this view to the caller. Since the std::string_view we return to the caller is still a view of m_string , it is not dangling.
The end result is we create 3 std::string_view instead of 3 std::string , which is more efficient.
14.11 — Overloading typecasts
User-defined conversions allow us to convert our class into another data type.
There are three things to note:
- To overload the function that casts our class to an int, we write a new function in our class called operator int(). Note that there is a space between the word operator and the type we are casting to. Such functions must be non-static members.
- User-defined conversions do not take parameters, as there is no way to pass arguments to them.
- User-defined conversions do not have a return type. C++ assumes you will be returning the correct type.
We can now also explicitly cast our Cents variable to an int:
You can provide user-defined conversions for any data type you wish, including your own user-defined data types!
Converting constructors vs overloaded typecasts
Overloaded typecasts and converting constructors perform similar roles: an overloaded typecast allows us to define a function that converts some program-defined type A into some other type B. A converting constructor allows us to define a function that creates some program-defined type A from some other type B. So when should you use each?
In general, a converting constructor should be preferred to an overloaded typecast, as it allows the type being constructed to own the construction.
There are a few cases where an overloaded typecast should be used instead:
- When providing a conversion to a fundamental type (since you can’t define constructors for these types). Most idiomatically, these are used to provide a conversion to bool for cases where it makes sense to be able to use an object in a conditional statement.
- When providing a conversion to a type you can’t add members to (e.g. a conversion to std::vector, since you can’t define constructors for these types either).
- When you do not want the type being constructed to be aware of the type being converted to. This can be helpful for avoiding circular dependencies. For example, std::string provides an overloaded typecast to std::string_view so that std::string_view doesn’t have to #include .
14.12 — The copy constructor
Recapping the types of initialization.
Since we’re going to talk a lot about initialization in the next few lessons, let’s first recap the types of initialization that C++ supports: direct (parenthesis) initialization, uniform (brace) initialization or copy (equals) initialization.
The copy constructor
A copy constructor is a special type of constructor used to create a new object as a copy of an existing object (of the same type).
The copy constructor’s parameter must be a reference
It is a requirement that the parameter of a copy constructor be a (const) reference. This makes sense: if the argument were passed by value, then we’d need the copy constructor to copy the argument into the parameter of the copy constructor (which would result in an infinite recursion).
Preventing copies
We can prevent copies of our classes from being made by making the copy constructor private:
Now when we try to compile our program, we’ll get a compile error since fCopy needs to use the copy constructor, but can not see it since the copy constructor has been declared as private.
The copy constructor may be elided
Why didn’t our copy constructor get called?
Note that initializing an anonymous object and then using that object to direct initialize our defined object takes two steps (one to create the anonymous object, one to call the copy constructor). However, the end result of initializing our defined object is essentially identical to just doing a direct initialization, which only takes one step.
For this reason, in such cases, the compiler is allowed to opt out of calling the copy constructor and just do a direct initialization instead. The process of omitting certain copy (or move) steps for performance purposes is called elision .
So although you wrote:
The compiler may change this to:
which only requires one constructor call (to Fraction(int, int)). Note that in cases where elision is used, any statements in the body of the copy constructor are not executed, even if they would have produced side effects (like printing to the screen)!
The rule of three and the rule of zero
The rule of three is a well known C++ principle that states that if a class requires a user-defined destructor, copy constructor, or copy assignment operator, then it probably requires all three. Not following the rule of three is likely to lead to malfunctioning code.
The rule of zero states, “Classes that have custom destructors, copy/move constructors or copy/move assignment operators should deal exclusively with ownership. Other classes should not have custom destructors, copy/move constructors or copy/move assignment operators.” (cite). In this context, “custom” means “user-defined”.
The best way to avoid having to implement these special functions is to use existing types that already support copy semantics (aka. not raw pointers). That way, the compiler-generated defaults for these special functions will behave as expected.
14.13 — Copy initialization
Copy initialization for classes.
Avoid using copy initialization, and use uniform initialization instead.
Other places copy initialization is used
There are a few other places copy initialization is used, but two of them are worth mentioning explicitly. When you pass or return a class by value, that process uses copy initialization.
In the above program, function makeNegative takes a Fraction by value and also returns a Fraction by value. When we run this program, we get:
The first copy constructor call happens when fiveThirds is passed as an argument into makeNegative() parameter f. The second call happens when the return value from makeNegative() is passed back to main().
14.14 — Converting constructors, explicit, and delete
Constructors eligible to be used for implicit conversions are called converting constructors (or conversion constructors).
The explicit keyword
Consider making your constructors and user-defined conversion member functions explicit to prevent implicit conversion errors.
The delete keyword
14.15 — overloading the assignment operator.
The copy assignment operator (operator=) is used to copy values from one object to another already existing object.
Copy assignment vs Copy constructor
The purpose of the copy constructor and the copy assignment operator are almost equivalent – both copy one object to another. However, the copy constructor initializes new objects, whereas the assignment operator replaces the contents of existing objects.
The difference between the copy constructor and the copy assignment operator causes a lot of confusion for new programmers, but it’s really not all that difficult. Summarizing:
- If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value).
- If a new object does not have to be created before the copying can occur, the assignment operator is used.
Overloading the assignment operator
Overloading the copy assignment operator (operator=) is fairly straightforward, with one specific caveat that we’ll get to. The copy assignment operator must be overloaded as a member function.
Issues due to self-assignment
Consider what happens in the overloaded operator= when the implicit object AND the passed in parameter (str) are both variable alex. In this case, m_data is the same as str.m_data. The first thing that happens is that the function checks to see if the implicit object already has a string. If so, it needs to delete it, so we don’t end up with a memory leak. In this case, m_data is allocated, so the function deletes m_data. But because str is the same as *this, the string that we wanted to copy has been deleted and m_data (and str.m_data) are dangling.
Later on, we allocate new memory to m_data (and str.m_data). So when we subsequently copy the data from str.m_data into m_data, we’re copying garbage, because str.m_data was never initialized.
Detecting and handling self-assignment
Fortunately, we can detect when self-assignment occurs. Here’s an updated implementation of our overloaded operator= for the MyString class:
By checking if the address of our implicit object is the same as the address of the object being passed in as a parameter, we can have our assignment operator just return immediately without doing any other work.
Because this is just a pointer comparison, it should be fast, and does not require operator== to be overloaded.
When not to handle self-assignment
The copy and swap idiom, default copy assignment operator.
Unlike other operators, the compiler will provide a default public copy assignment operator for your class if you do not provide one. This assignment operator does memberwise assignment (which is essentially the same as the memberwise initialization that default copy constructors do).
Just like other constructors and operators, you can prevent assignments from being made by making your copy assignment operator private or using the delete keyword:
14.16 — Shallow vs. deep copying
Shallow copying.
Because C++ does not know much about your class, the default copy constructor and default assignment operators it provides use a copying method known as a memberwise copy (also known as a shallow copy ).
However, when designing classes that handle dynamically allocated memory, memberwise (shallow) copying can get us in a lot of trouble! This is because shallow copies of a pointer just copy the address of the pointer – it does not allocate any memory or copy the contents being pointed to!
The root of this problem is the shallow copy done by the copy constructor – doing a shallow copy on pointer values in a copy constructor or overloaded assignment operator is almost always asking for trouble.
Deep copying
One answer to this problem is to do a deep copy on any non-null pointers being copied. A deep copy allocates memory for the copy and then copies the actual value, so that the copy lives in distinct memory from the source. This way, the copy and source are distinct and will not affect each other in any way. Doing deep copies requires that we write our own copy constructors and overloaded assignment operators.
A better solution
Classes in the standard library that deal with dynamic memory, such as std::string and std::vector, handle all of their memory management, and have overloaded copy constructors and assignment operators that do proper deep copying. So instead of doing your own memory management, you can just initialize or assign them like normal fundamental variables! That makes these classes simpler to use, less error-prone, and you don’t have to spend time writing your own overloaded functions!
The default copy constructor and default assignment operators do shallow copies, which is fine for classes that contain no dynamically allocated variables. Classes with dynamically allocated variables need to have a copy constructor and assignment operator that do a deep copy. Favor using classes in the standard library over doing your own memory management.
14.17 — Overloading operators and function templates
14.x — chapter 14 comprehensive quiz.
“相关推荐”对你有帮助么?

请填写红包祝福语或标题

你的鼓励将是我创作的最大动力

您的余额不足,请更换扫码支付或 充值

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。 2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

- Spring Boot
- windows server
(原創) 哪些地方會用到Copy Constructor和Assignment Operator? (C/C++)
分类: java 日期:2023-03-02 20:04:59.
C#、Java都沒有copy constructor,所以這對大部分programmer都很陌生,簡單地說,凡需要copy的地方,就需要copy constructor:
1.由copy-initialization方式建立物件。 Ex. Foo foo1; Foo foo2(foo1); 以上直接使用copy constructor。 string s = "C++ Primer"; Foo foo = Foo(); 此時是先由default constructor建立一個temporary object後,再由copy constructor將temporary object 『copy』給物件。 2.以by value的方式傳進function和由function return值。 Ex. int Foo(int n); 只要不是使用by reference的方式,就得使用copy constructor。
3.建立STL container中的element。 Ex.vector<string> svec(5); 先由string的default constructor建立一個temporary string object,再由string的copy constructor『copy』到vector中每個element。
4.由initialization list建立array。 Ex.int ia[] = {1, 2, 3}; 先由int default contructor先建立temporary int object,再由int的copy contructor『copy』到array中。
所以copy constructor其實是無所不在的,只是我們從來沒有發現,雖然C++ compiler會自己synthesize copy constructor,但也允許我們自己定義自己的Copy Constructor,這與C#、Java不同。 而assignment operator呢? Foo foo1; Foo foo2; foo2 = foo1; 以上會執行foo2的assignment operator。 所以簡單的說,copy constructor和assignment operator都在做『copy』的動作,當資料是pointer,也就是動態資料時,就必須重新改寫,否則只會copy pointer,而不是copy data。
本文由www.shitiquan.com整理发布,转载请保留本文链接。
https://www.smslm.com/article/683254.html
- (原創) 哪些地方會用到Copy Constructor和Assignment Operator? (C/C++) 2023.03.02
- Constructor
- 最难的编程语言是哪一门?| InfoQ编程语言2月排行榜
- 贝壳跨端之路——从 0 到 1 接入Flutter实战
- 一位有钱的程序员给了我三条改变人生的建议
- 闪马智能:Serverless 如何赋能大前端?| GMTC 2021
- 最有“钱”景的编程语言、Swift体系和一个名叫Web 3的幽灵
- Java 开发、全自研的开源监控组件来了,让 openGauss 更香
- java(01)__Java基础
- PHP是最糟糕的编程语言?
- Java SE之基础篇(七)——方法
- Java近期新闻综述:Spring 6.0和SpringBoot 3.0、OpenJDK和Quarkus更新的路线图

IMAGES
VIDEO
COMMENTS
The copy constructor performs first-time initialization of objects that used to be raw memory. The assignment operator, OTOH, overrides existing values with new ones. More often than never, this involves dismissing old resources (for example, memory) and allocating new ones.
There are two obvious differences between copy constructor and copy assignment operator. copy constructor NO NEED to delete old elements, it just copy construct a new object. (as it Vector v2) copy constructor NO NEED to return the this pointer. (Furthermore, all the constructor does not return a value). Share Improve this answer Follow
Copy constructor and Assignment operator are similar as they are both used to initialize one object using another object. But, there are some basic differences between them: Consider the following C++ program. CPP #include <iostream> #include <stdio.h> using namespace std; class Test { public: Test () {} Test (const Test& t) {
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. [] Implicitly-declared copy assignment operatoIf no user-defined copy assignment operators are provided for a class type (struct, class, or union), the compiler will always declare one as an inline public member of the class.
The assignment operator for a class is what allows you to use = to assign one instance to another. For example: 1 2 MyClass c1, c2; c1 = c2; There are actually several different signatures that an assignment operator can have: (1) MyClass& operator= ( const MyClass& rhs ); (2) MyClass& operator= ( MyClass& rhs );
Rule of three. If a class requires a user-defined destructor, a user-defined copy constructor, or a user-defined copy assignment operator, it almost certainly requires all three.. Because C++ copies and copy-assigns objects of user-defined types in various situations (passing/returning by value, manipulating a container, etc), these special member functions will be called, if accessible, and ...
Assignment operator overloading is binary operator overloading. Overloading assignment operator in C++ copies all values of one object to another object. Only a non-static member function should be used to overload the assignment operator. We can't directly use the Assignment Operator on objects.
You must attach appropriate copying semantics to each class, as follows: Use an assignment operator operator= that returns a reference to the class type and takes one parameter that's passed by const reference—for example ClassName& operator= (const ClassName& x);. Use the copy constructor.
A copy constructor is an overloaded constructor whereas an assignment operator is a bitwise operator. Using copy constructor you can initialize a new object with an already existing object. On the other hand, an assignment operator copies one object to the other object, both of which are already in existence.
If a new object has to be created before the copying can occur, the copy constructor is used (note: this includes passing or returning objects by value). If a new object does not have to be created before the copying can occur, the assignment operator is used. Overloading the assignment operator
Assignment Operators Overloading in C++ Previous Page Next Page You can overload the assignment operator (=) just as you can other operators and it can be used to create an object just like the copy constructor. Following example explains how an assignment operator can be overloaded. Live Demo
A copy constructor is a special type of constructor used to create a new object as a copy of an existing object (of the same type). And much like a default constructor, if you do not provide a copy constructor for your classes, C++ will create a public copy constructor for you. Because the compiler does not know much about your class, by ...
5. Move operator. General form. The purpose of using the move operator is the same as that of the move constructor - to speed up program execution by avoiding direct copying of data when assigning so-called rvalue references, which are used in expressions on the right side of the assignment operator.
14.15 — Overloading the assignment operator. The copy assignment operator (operator=) is used to copy values from one object to another already existing object. Copy assignment vs Copy constructor. The purpose of the copy constructor and the copy assignment operator are almost equivalent - both copy one object to another.
此時是先由default constructor建立一個temporary object後,再由copy constructor將temporary object 『copy』給物件。 2.以by value的方式傳進function和由function return值。 Ex. int Foo(int n); 只要不是使用by reference的方式,就得使用copy constructor。 3.建立STL container中的element。 Ex.vector<string ...