Resource management in C++ is tricky because the language gives you direct control over memory, but with that control comes responsibility. When classes manage resources like dynamic memory, shallow copies (the default behavior) can lead to issues such as double-deletion, dangling pointers, and undefined behavior. Without properly implementing copy constructors and assignment operators, two objects might unknowingly share the same resource, causing subtle and hard-to-debug errors. This makes it essential to understand deep copying, ownership, and cleanup to write safe and reliable C++ code.
Passing by Value in Constructors
void f(String t) {
// ...
}
void h() {
String s("Hello");
}- Passing by value creates a copy of the original object.
- If the class manages dynamic memory (e.g., a
char*array), this can lead to:- Aliasing: both
sandtpoint to the same array. - Dangling pointers: when
sis destroyed,tis left pointing to freed memory. - Undefined behavior and potential crashes.
- Aliasing: both
💡 To prevent this, implement a copy constructor that performs a deep copy of the internal resource.
String::String(const String& other) {
m_len = other.m_len;
m_text = new char[m_len + 1]; // Allocate new memory
strcpy(m_text, other.m_text); // Deep copy the content
}constensures the original object isn’t modified.- Even though
m_textis private, the copy constructor can access it since both objects are of the same class.
Assignment vs. Copying
s = t; // Assignment operator
String x(s); // Copy constructor
String x = s; // Also invokes copy constructorvoid f(String t) {
// Copy constructor is called
}
void h() {
String s("Hello");
f(s); // Copy constructor
String u("wow");
u = s; // Assignment operator
}- Copy constructor is used when creating a new object from an existing one.
- Assignment operator is used when assigning a new value to an already constructed object.
- Both must be defined separately to avoid shallow copies and memory issues.
- If not explicitly defined, the compiler provides default versions — which do shallow copies and can be dangerous for resources like dynamic memory.
Copy Constructors
A copy constructor defines how a new object is initialized from an existing object of the same type.
- Ensures proper duplication of internal state and resources.
- Essential when dealing with classes that manage dynamic memory or non-trivial resources.
- Same-class objects can access each other’s private members, which allows for safe copying of internal data.
Assignment Operators
An assignment operator defines how to assign the value of one object to another existing object.
class Circle {
private:
string* m_arr;
public:
// Assignment operator declaration
Circle& operator=(const Circle& src);
};- Used when doing
a = b; - The operator must:
- Check for self-assignment.
- Free existing resources to prevent memory leaks.
- Perform a deep copy of the source object.
- Return a reference to
*thisfor chaining.
🧠 Always implement both the copy constructor and assignment operator when managing resources to ensure safe, predictable behavior.
Linked Map of Contexts