Course Content#
Types and Variables#
Can be understood as aliases for classes and objects
-
- C++ only specifies the minimum bit size for types, so some compilers can implement more bits
-
- Refer to cppreference——Basic Types
-
Types#
= Type Data + Type Operations
- For example: int = 4-byte data + basic operations (
+-*/%
), can be associated with data structures, int and double types are essentially data structures - Type data + type operations ➡️ member attributes + member methods
- Can be understood as an enhanced version of C language struct (can hold attributes but cannot hold methods)
Access Permissions
First distinguish between concepts inside and outside the class
Access permissions are set within the class, controlling whether the outside can access the inside
- public: Public
- Accessible both inside and outside the class
- private: Private
- Only accessible by methods within the class
- protected: Protected
- Accessible by inherited classes in addition to the class itself
- friendly: Friend
- Functions modified by it can access private and protected members within the class
Constructors and Destructors#
The lifecycle of an object: Construct → Use → Destruct
Three Basic Types of Constructors#
Associating local variable initialization, objects also need initialization
Constructor Type | Usage | ⚠️Note |
---|---|---|
Default Constructor | People bob; Prototype: People(); | 1. Zero-parameter constructor 2. Automatically generated by the compiler |
Conversion Constructor | People bob("DoubleLLL"); Prototype: People(string name); | 1. A parameterized constructor with one parameter 2. This parameter is passed to the class's member variable and is not a const reference of the class itself [PS] Similar to implicit type conversion |
Copy Constructor | People bob(hug); Prototype: People(const People &a); | 1. A special parameterized constructor that takes an object of the same class 2. Not equivalent to the assignment operator "=" [PS] Easier to handle as const & |
Destructor#
Destroying an object
Prototype: ~People();
⚠️Note:
-
No parameters and no return value
-
Used for resource recovery
Summary#
No return value, function name is the same as the class name
- In engineering development, the functions of constructors and destructors are designed to be very simple
- ❓ Why not perform a lot of resource allocation in the constructor?
- Reason: Bugs in constructors are difficult for the compiler to detect
- Solution: Pseudo-constructors, pseudo-destructors; Factory design pattern
- [+] Move Constructor (another key constructor, to be learned later)
- From the C++11 standard——the standard that brought C++ back to glory
- Before this, STL had poor performance due to C++'s language features, which did not distinguish between lvalues and rvalues, leading to a large number of copy operations during STL usage, especially deep copy operations, significantly affecting performance
- After this, the concept of rvalues was introduced, along with move constructors
Return Value Optimization (RVO)#
The compiler has RVO enabled by default
Introduction#
Object a is constructed through the return value of fun()

Output result:

- Theoretically: should output 1 time transform and 2 times copy
- See detailed analysis below 👇
- In reality: no copy output, and the value of a.x is the x value from the temp object, meaning the address of the local variable temp was directly used as the address of object a (the data area of object a was allocated first, see below)
- temp is more like a reference
- Compiler optimization exists, namely return value optimization RVO🌟
Detailed Analysis#
Object initialization process: 1. Allocate object data area ➡️ 2. Match constructor ➡️ 3. Complete construction
- After understanding the object initialization process, analyze the construction process in the above code:
-
- First, allocate the data area for object a
- Then, enter the func function, allocate the data area for object temp, and initialize the local variable temp through "conversion constructor"——A temp(69);
- Next, through "copy constructor", copy temp to a temporary anonymous object and destroy object temp——return temp;
- Finally, through "copy constructor", copy the temporary anonymous object to a, destroying the temporary anonymous object——Aa = func();
- 👉 Thus, the process includes 1 conversion constructor and 2 copy constructors
-
- Compiler optimization
- The first optimization cancels the first "copy constructor", directly copying temp to a (optimization under Windows)
- The second optimization cancels the second "copy constructor", directly making temp point to a (optimization under Mac and Linux)
After Disabling RVO#
Compile the source file with g++ -fno-elide-constructors to disable RVO

- Two additional "copy constructors" appeared, see detailed analysis above
Points to Note#
- The compiler essentially implements RVO by replacing the this pointer
- Because the compiler generally optimizes copy constructors, in engineering development, do not change the semantics of the copy constructor
- That is: only perform copy operations in the copy constructor, and do not perform other operations
- For example: adding 1 to the copied attribute in the copy constructor does not conform to the semantics of the copy constructor, and when the compiler optimizes the copy constructor, the result will be inconsistent with that before optimization
+ Optimization of Assignment Operations#
RVO also exists——optimized one copy constructor, copying the local variable to a temporary anonymous object

- Added the code in the red box
- Result before optimization:
-
- 1 "conversion constructor" + 1 "copy constructor"
-
- Result after optimization:
-
- 1 "copy constructor"
-
+ Analysis of Copy Constructor Calls#
How is the copy constructor called under various writing methods?
Scenario: Class A contains an object d of a custom class Data, the red box shows the added code

「Focus on line 29; disable RVO compilation, otherwise the copy constructor will be skipped」
- Custom copy constructor, explicitly copying each member attribute, i.e., line 29 remains unchanged
-
- When constructing object d, the copy constructor of the Data class will be called
- Custom copy constructor, not explicitly copying each member attribute, i.e., remove ",d(a.d)"
-
- When constructing object d, the default constructor of the Data class will be called (if not explicitly copied during customization, it matches the default constructor)
- Not customizing the copy constructor, the compiler automatically adds the default copy constructor, i.e., remove lines 29-31
-
- When constructing object d, the copy constructor of the Data class (the compiler's default) will be called
Conclusion:
❗️ To achieve the expected result, when customizing the copy constructor, each member attribute should be explicitly copied
- If the custom copy constructor does nothing, then that function will do nothing
Other Knowledge Points#
References#
A reference is an alias for the bound object
- ❗️ References need to be initialized at the time of definition, i.e., binding the object, such as:
- People a;
- Initialize at definition: People &b = a;
- Otherwise: People &b; b = c; will cause ambiguity——binding object or assignment?
Class Attributes and Methods#
Added with the static keyword
Different from member attributes (unique to each object) and member methods (this pointer points to the current object)
- Class attributes: Attributes shared by all objects of the class
- Globally unique, shared
- For example: the number of all humans——the quantity of all objects in humanity
- Class methods: Methods that do not belong to a specific object
- Not bound to objects, cannot access this pointer
- For example: testing whether a certain height is a valid height
const Methods#
Do not change the object's member attributes, cannot call non-const member functions
- Provided for const objects (none of its attributes can be changed)
⚠️:
mutable: Mutable, its modified variable can change in const methods
default and delete#
Control of default functions, C++11
- default: Explicitly use the rules provided by the compiler by default
- Only applicable to special member functions of the class (default constructor, destructor, copy constructor, copy assignment operator), and that special member function has no default parameters
- ❗️ This feature has no functional significance; it is C++'s design philosophy: focusing on readability, maintainability, etc.
- Understanding this philosophy can enhance one's aesthetic standards in C++
- delete: Explicitly disable a certain function
struct and class#
- struct
- Default access permission: public (blacklist mechanism, needs to explicitly define private members)
- Also used to define classes, with member attributes and methods, to distinguish from C
- class
- Default access permission: private (whitelist mechanism: needs to explicitly define public members)
❓: Why does C++ retain the struct keyword? Why is the default permission public?
- All for compatibility with C language, to reduce the difficulty of promotion
PS: Front-end language JavaScript reduces promotion difficulty by leveraging the popularity of Java, fundamentally unrelated to Java
Code Demonstration#
Example of a Class#

- Declaration and definition of attributes and methods in the class are recommended to be separated
- The this pointer is only used in member methods, pointing to the address of the current object
Simple Implementation of cout#

- cout is an object, a high-level variable
- Returning its own reference can achieve continuous cout, the reason for using references will be understood later
- Strings need to be received with const type variables, otherwise, there will be warnings, because strings are literals
- The essence of namespaces: the same object name can exist in different namespaces
Constructors and Destructors#


Output result:

1) Discussion on Destruction Order#
-
- Construction order: object a, object b
- Destruction order: object b, object a
- ❓ Why is the order of destructor calls reversed? Is it due to a special case generated by the compiler, or is it a normal language feature? 👉 Language feature
- The construction of object b may depend on information from object a ➡️ during destruction, object b may also need information from object a ➡️ object b must be destructed before object a
- ❗️ Whoever constructs first, destructs last
- PS
- This is independent of whether objects are placed in heap space or stack space; experiments show that the destruction order is always reversed
- Can be considered a form of topological order
2) Conversion Constructor#
- ❓ Why is it called a conversion constructor (constructor with a single parameter)?
- It converts a variable into an object of that type
- 🌟 a=123 involves operator overloading: implicit type conversion ➡️ assignment ➡️ destruction, see code for details
3) Copy Constructor#
- Add reference: Prevent infinite calls to the copy constructor
- ❗️ If the copy constructor is: A(A a) {}, then A b = a; will occur,
- Because [parameter a] is not a reference (pass by value), it first needs to copy [object a] to [parameter a] to create a temporary object
- At this point, the copy constructor will be called again, and this copy constructor will also go through the above process
- Thus, infinite recursion occurs
- PS: References do not produce any copy behavior, more convenient than pointers
- Add const: Prevent const type objects from using non-const type copy constructors, resulting in an error
- Also prevents the copied object from being modified
Note:
- When defining an object, "=" calls the copy constructor, not the assignment operation, for example, A b = a
4) Reflection#
- When is an object considered fully constructed?
- 「Refer to the code, taking the default constructor as an example」
- Functionally, the construction [logically]: by line 46, the constructor appears to have completed execution
- Compiler's construction [actually]: by line 39, the object's members can already be called❗️🌟
- Through the code in the reflection section, it can be understood:
- Scenario: Adding a parameterized constructor to the Data class causes the compiler's default constructor to be deleted
- Process: When generating an object of class A, the member attributes Data class objects p and q need to be fully constructed, while the default constructor of the Data class has been deleted
- Result
- If p and q are not initialized using an initialization list, an error will occur
- If using an initialization list, it is feasible; the initialization list belongs to what the compiler refers to as construction
- ❗️ This indicates that the compiler's construction is completed after the function declaration (line 39)
- ⚠️:
- The compiler will automatically add default constructors and copy constructors
- Construction behavior should be placed in what the compiler refers to as construction, such as using initialization lists
+) Lvalue References#
- To be learned later
+) Friend Functions#
- Declared within the class (ensuring it is approved by the class's manager)
- Implemented outside the class, essentially a function outside the class but can access private member attributes within the class
Deep Copy, Shallow Copy#
Copying objects: Arrays

- The copy constructor automatically added by the compiler performs a shallow copy
- For pointers, only the address is copied, so modifications to the copied object will affect the original object
- Custom deep copy version of the copy constructor
- For pointers, copy the value of the address it points to
- PS: Constructors are only called during initialization, and there is no behavior of copying itself
⚠️:
- To adapt to the overloaded "<<" with const parameters, a const version of "[]" overload needs to be implemented
- The end in the Array class has no relation to the end data of the array; it is just used to monitor array out-of-bounds situations
Analysis of Differences Between new and malloc#

Output result:

- Both malloc and new can allocate space, corresponding to free and delete (for arrays, delete[])
- new automatically calls the constructor, and the corresponding delete automatically calls the destructor; while malloc and free do not
- malloc + new can achieve in-place construction, commonly used in deep copies, where new can correspond to constructors of different classes
Class Attributes and Methods, const, mutable#

- Class attributes: declared with static inside the class, initialized outside without static
- Class methods: can be called in two ways, either through an object or the class name
- Therefore, methods called by objects are not necessarily member methods; they can also be class methods
- const: const objects can only call const methods, and const methods can only call const methods
- mutable: Variables modified by it can change in const methods
default, delete#
Functional Requirement: Prevent objects of a certain class from being copied

- Disable copy constructors and assignment operators
- Copy constructor: set to =delete, or place it in private access
- Assignment operator overload function: also set to =delete (never usable for assignment), or place it in private access (only methods within the class can use assignment)
- PS: The assignment operator must consider both const and non-const versions
- ❓ To truly prevent an object from being copied, both the copy constructor and assignment operator overload should be set to =delete; otherwise, methods within the class can still copy the object
Additional Knowledge Points#
- Curly braces after the constructor
- Adding curly braces indicates it is a function implementation
- Not adding curly braces means it is just a function declaration, and a dedicated implementation still needs to be written
Points for Reflection#
- Pay attention to many things the compiler does by default; this is the complexity of C++
Tips#
- C++
- Learning method: Learn by categorizing according to programming paradigms
- Learning focus: The processing flow of the program [far more complex than C]