new allocates an object on the heap and constructs it; delete destroys it and frees the memory. Every new needs exactly one matching delete — which is why modern C++ hides both inside smart pointers and containers.
Syntax
#include <iostream>
#include <string>
int main() {
int* n = new int(42); // one int
std::string* s = new std::string("heap");
int* arr = new int[4]{1, 2, 3, 4}; // array
std::cout << *n << ' ' << *s << ' ' << s->size() << ' ' << arr[3] << '\n';
delete n; // single object → delete
delete s;
delete[] arr; // array → delete[]
n = nullptr; // avoid a dangling pointer
}42 heap 4 4malloc / free (C) | new / delete (C++) | |
|---|---|---|
| Constructs/destroys objects | No — raw bytes | Yes — calls constructor / destructor |
| Returns | void* (needs a cast in C++) | Typed T* |
| On failure | Returns NULL | Throws std::bad_alloc (or nullptr with new (std::nothrow)) |
| Size | You compute bytes | Computed from the type |
| Can be overloaded | No | Yes (operator new) |
The classic bugs
#include <iostream>
int main() {
int* p = new int(7);
delete p;
std::cout << *p << '\n'; // AddressSanitizer: heap-use-after-free
}int main() {
int* arr = new int[10];
delete arr; // clang -Wall rejects it; at run time ASan reports alloc-dealloc-mismatch
}Leaks via exceptions — and the fix
#include <iostream>
#include <memory>
#include <stdexcept>
#include <vector>
void risky(bool fail) {
// int* buf = new int[100]; ... delete[] buf; ← leaks if anything in between throws
auto buf = std::make_unique<int[]>(100); // freed automatically, even on exceptions
std::vector<int> better(100); // or simply use a container
buf[0] = better[0] = 1;
if (fail) throw std::runtime_error("boom");
}
int main() {
try { risky(true); } catch (const std::exception& e) { std::cout << "caught " << e.what() << ", no leak\n"; }
}caught boom, no leak2-D dynamic arrays
#include <iostream>
#include <vector>
int main() {
int rows = 3, cols = 4;
std::vector<std::vector<int>> grid(rows, std::vector<int>(cols, 0)); // no new/delete needed
grid[2][3] = 9;
std::vector<int> flat(rows * cols); // one block: faster
flat[2 * cols + 3] = 9; // row-major index
std::cout << grid[2][3] << ' ' << flat[11] << '\n';
}9 9What's the difference between delete and delete[]?
What happens if new fails?