Learning C++ has been a journey full of traps. Here are three I hit — hope they save you some debugging time.
🎣 Trap 1: new[] + delete(instead of delete[])
Wrong Code
int* a = new int[3];
// delete a; ❌ --> undefined
class MyClass{
public:
~MyClass(){
std::cout<<"delete successfully"<<std::endl;
}
}
int main(){
MyClass* mc = new MyClass[2];
//delete mc; ❌ -> only outputs one "delete successfully"
What Happens
C++ standard clearly states that this is undefined behavior. Relying on it is extremely dangerous — different compilers, optimization levels, and platforms may behave completely differently.
new[] + delete only calls the destructor once, while delete[] calls it for every element in the array. Using delete instead of delete[] causes resource leaks for the remaining elements.
How to Fix
int* a = new int[3];
delete[] a; -> ✔
class MyClass{
public:
~MyClass(){
std::cout<<"delete sucessfully"<<std::endl;
}
};
int main(){
MyClass* mc = new MyClass[2];
delete[] mc; -> ✔ outputs "delete successfully" twice
}
🎣 Trap 2: cin + getline eating your input
Wrong Code
int age;
std::string name;
std::cout<<"Enter age: ";
std::cin>>age;
std::cout<<"Enter name: ";
std::getline(cin, name); // ❌ name ends up empty!
std::cout<<name<<std::endl;
What Happens
cin leaves a newline character (\n) in the input buffer, and getline reads it immediately — so it stops before you even type anything.
Why
cin >> reads the value you type but leaves \n in the buffer. getline stops reading when it encounters \n, so it grabs that leftover newline and returns an empty string.
How to Fix
std::cin >> age;
cin.ignore(); // 👈 Eat the leftover newline
std::getline(cin, name);
🎣 Trap 3: Copy constructor vs copy assignment
class FixArray{
std::string name_;
int* data_;
size_t size_;
public:
~FixArray(){
delete[] data_;
}
FixArray(const FixArray& other) : FixArray(other.size_, other.name_){
std::copy(other.data_, other.data_ + size_, data_);
}
FixArray& operator=(const FixArray& other){
if(this != &other){
int* new_data = new int[other.size_];
std::copy(other.data_, other.data_ + other.size_, new_data);
delete[] data_;
data_ = new_data;
size_ = other.size_;
name_ = other.name_;
}
return *this;
}
};
Many beginners can't tell the difference between a copy constructor and a copy assignment. Actually, it's quite simple:
// Copy constructor: creating a new object from an existing one
FixArray fa(10, "example");
FixArray fb = fa; // 👈 copy constructor called
// Copy assignment: assigning to an already-existing object
FixArray fc(5, "other");
fc = fa; // 👈 copy assignment called
Copy constructor — creates a brand new object as a copy of an existing one.
Copy assignment — replaces the contents of an already-existing object with another object's data.
The key difference: copy constructor builds something from nothing; copy assignment replaces something that already exists.
These are three traps I hit while learning C++. If you're a beginner too, I hope this saves you some debugging time. Have you encountered other tricky C++ traps? Share them below!
Top comments (1)
Nice summary! One thing I’d add is that the biggest beginner trap today is often using new/delete at all. Modern C++ encourages RAII and smart pointers (std::unique_ptr, std::shared_ptr) or containers like std::vector, which eliminate many of these memory management pitfalls. Learning why delete[] matters is important—but learning when you don’t need manual memory management is even more valuable.