# Do’s and Don’ts of C++: Writing Safer and More Reliable Code

C++ gives developers a lot of control over memory and performance. That control is also the reason many bugs in C++ are subtle, hard to detect, and sometimes disastrous.  
Most of these issues are not caused by advanced features, but by small, everyday mistakes.

This blog covers practical do’s and don’ts in C++ that help you write safer, more modern, and more maintainable code.

---

## Don’t Access Arrays Out of Bounds

### Do Prefer Safer Containers Like `std::vector`

### Problematic code using arrays

```cpp
int arr[3] = {1, 2, 3};
cout << arr[5];   // Undefined behavior
```

This code compiles successfully. However, accessing an index outside the array bounds leads to undefined behavior. The program might crash, print garbage values, or appear to work correctly and fail later.

### Safer approach using vectors

```cpp
vector<int> v = {1, 2, 3};
cout << v.at(5);  // Throws std::out_of_range
```

The `at()` method performs bounds checking and throws an exception when the index is invalid. This makes bugs visible instead of silently corrupting memory.

---

## Don’t Use Raw Arrays by Default

### Do Use `std::vector` or `std::array`

Raw arrays have fixed size and no built-in safety.

```cpp
int arr[100];
```

Preferred alternatives:

```cpp
vector<int> v(100);      // Dynamic size
array<int, 100> a;       // Fixed size but safer
```

These containers integrate well with the STL and reduce the chances of memory-related bugs.

---

## Don’t Manage Memory Manually

### Do Use Smart Pointers

Manual memory management is error-prone.

```cpp
int* p = new int(10);
// ...
delete p;
```

Forgetting `delete`, deleting twice, or throwing an exception before cleanup can cause leaks or crashes.

Modern C++ approach:

```cpp
auto p = make_unique<int>(10);
```

Smart pointers automatically manage object lifetimes and are safer in the presence of exceptions.

---

## Don’t Pass Large Objects by Value

### Do Pass by Reference or Const Reference

Passing containers by value causes unnecessary copying.

```cpp
void process(vector<int> v);  // Inefficient
```

Better approach:

```cpp
void process(const vector<int>& v);
```

This avoids copying while also preventing accidental modification.

---

## Don’t Use `using namespace std;` in Header Files

### Do Use Qualified Names

```cpp
using namespace std;  // Avoid in headers
```

This can cause name collisions in large projects.

Preferred:

```cpp
std::vector<int> v;
std::cout << "Hello";
```

---

## Don’t Use C-Style Strings

### Do Use `std::string`

C-style strings are a common source of buffer overflows.

```cpp
char name[10];
strcpy(name, "VeryLongName");  // Unsafe
```

Safer alternative:

```cpp
string name = "VeryLongName";
```

`std::string` manages memory automatically and grows as needed.

---

## Don’t Modify a Container While Iterating Over It Incorrectly

### Do Use Iterators Carefully

Incorrect:

```cpp
for (int x : v) {
    if (x == 0)
        v.push_back(x);
}
```

Correct:

```cpp
for (auto it = v.begin(); it != v.end(); ) {
    if (*it == 0)
        it = v.erase(it);
    else
        ++it;
}
```

Modifying a container during iteration requires careful handling to avoid invalidated iterators.

---

## Don’t Ignore `const`

### Do Use `const` Wherever Possible

```cpp
void print(const vector<int>& v);
```

Using `const`:

* Prevents accidental modification
    
* Improves readability
    
* Helps the compiler optimize code
    

---

## Don’t Write C++ Like C

### Do Use Modern C++ Practices

Avoid:

* Raw pointers
    
* Manual memory management
    
* C-style casts
    
* Macros for constants
    

Prefer:

* STL containers
    
* Smart pointers
    
* `constexpr`, `enum class`
    
* Range-based loops
    
* RAII principles
