Most people think "new" just creates an object. It actually does two things. When you write: int* p = new int(10); It: • Allocates memory • Constructs the object But what if you already have memory? And only want to construct an object there? That’s where placement new comes in. char buffer[sizeof(int)]; int* p = new (buffer) int(10); Here: • No memory allocation happens • The object is constructed inside existing memory This means: Allocation and construction are actually separate steps in C++. Why this matters: • Custom memory management • Object pools • Performance-critical systems But there’s a catch. You are responsible for: • Managing the memory • Calling the destructor manually This is not something you use every day. But it shows how much control C++ gives over memory and object lifetimes. Didn’t expect this level of control at first — kinda blew my mind. #cpp #cplusplus #systems #softwareengineering #programming
C++ Placement New Allocates Memory and Constructs Objects
More Relevant Posts
-
There was a project some years ago where the customer wanted the firmware written in C++. Object oriented, clean abstractions, the works. The hardware was a small microcontroller with extremely limited RAM and no dynamic memory allocation — no heap, effectively. C++ without new and delete feels like cooking without fire. Technically possible. Deeply uncomfortable at first. The team's initial reaction was to push back and ask for either more capable hardware or permission to use C. Neither was on the table. The hardware was fixed. The language preference was fixed. So we had to figure it out. What followed was one of the more interesting firmware exercises I have been part of. We used placement new to work with statically allocated memory pools. Every object had a fixed home determined at compile time. Templates replaced what would normally be runtime polymorphism. The linker script became something we understood intimately rather than accepted as given. It was constrained. It was occasionally maddening. But the output was genuinely clean firmware that the customer's team — used to higher level C++ — could read and maintain without needing to relearn how to think. The lesson I took from it was not a technical one. It was that constraints force a quality of thinking that comfort never does. Some of the cleanest designs I have seen came out of situations where the easy path was simply not available. The projects that stretch you the most are rarely the ones with the best specs. What is the tightest constraint a project has ever pushed you through? #CPlusPlus #EmbeddedSystems #Firmware #Engineering #PandianPosts #Embien
To view or add a comment, sign in
-
💡 Understanding union vs std::variant in C++ (from low-level to modern safety) Let’s start with a classic C++ concept: union. A union allows multiple members to share the same memory location. Instead of allocating space for each field, it uses only enough memory for the largest one. union Value { Node* p; int i; }; Here: p and i occupy the same address The union size = max(sizeof(Node*), sizeof(int)) 👉 This is efficient — but comes with a cost. ⚠️ The Problem A union does not track which value is active. Value v; v.i = 42; // Later... std::cout << v.p; // ❌ Undefined behavior You’re responsible for remembering what’s stored. That’s why we often add a manual tag: enum class Type { ptr, num }; struct Entry { Type t; Value v; }; And use it like: if (entry.t == Type::num) std::cout << entry.v.i; This pattern is called a tagged union. 🧠 The Modern C++ Solution: std::variant C++ now gives us a safer, cleaner alternative: #include <variant> using Value = std::variant<Node*, int>; Now: The type knows what it currently holds No manual tag needed No undefined behavior (if used correctly) ✅ Accessing the value safely Value v = 42; if (std::holds_alternative<int>(v)) { std::cout << std::get<int>(v); } Or even better: std::visit([](auto&& val) { std::cout << val; }, v); In modern C++, the default choice should almost always be: 👉 std::variant over raw union #cpp #cplusplus #moderncpp #programming #softwareengineering #systemsprogramming #lowlevel #memorymanagement #cpp17 #developers
To view or add a comment, sign in
-
In my last post, I talked about placement new. But there’s something important that can easily go wrong. When you use placement new: char buffer[sizeof(int)]; int* p = new (buffer) int(10); No memory is allocated. You’re just constructing an object in existing memory. Now the question is: Can you just call delete? delete p; No. Why? Because delete does two things: • Calls the destructor • Frees memory But in this case: • Memory was never allocated using new • So freeing it is invalid What you should do instead: p->~int(); // manually call destructor This is the key idea: Placement new separates: • Memory allocation • Object construction So you also need to handle destruction manually. If you use delete here, it leads to undefined behavior. And these are the kinds of mistakes that are hard to debug. This was something I completely missed at first. But once it clicked, it made the whole concept much clearer. C++ gives you a lot of control. But it also expects you to handle things carefully. #cpp #cplusplus #systems #softwareengineering #programming
To view or add a comment, sign in
-
One thing that really clicked for me in modern C++: T&& is not always an rvalue reference. Inside a template, T&& is a forwarding reference — it binds to both lvalues and rvalues, and the type T adapts to whatever the caller passes. The mechanic: caller → T&& x → std::forward<T>(x) → same value category, preserved std::forward is not magic — it is a conditional cast that passes the argument along as it was received. That is why you get: perfect forwarding no unnecessary copies move semantics through wrappers generic APIs that stay efficient The real takeaway: When you use T&& in a template, you are not writing an rvalue reference — you are writing code that adapts to the caller. std::forward doesn't detect — it preserves. #cpp #cplusplus #moderncpp #templates #movesemantics #softwareengineering #programming
To view or add a comment, sign in
-
-
This project is a DLL injector developed in C++ that allows users to inject external DLL files into target processes. It supports multiple injection methods and manual mapping features, enabling code execution and dependency resolution. 🔗 https://lnkd.in/gaMEk-Ez
To view or add a comment, sign in
-
I came across std::array in some C++ code recently and had an honest realization — I almost never reach for it in my day-to-day work. For simple use-cases, raw C-style arrays still feel more direct. No wrappers, no abstractions — just a fixed block of memory that does exactly what you expect. But when things get even slightly complex, my instinct immediately shifts to std::vector. Dynamic sizing, cleaner memory management, and overall flexibility make it hard to ignore. So where does std::array really fit? It is safer than C arrays — no decay to pointers, better integration with STL algorithms, and compile-time size guarantees. But in practice, it often sits in this awkward middle ground: * Too “structured” for trivial use * Too limited for dynamic scenarios That said, I’ve started noticing a few areas where it actually makes sense: * Fixed-size buffers where size is known at compile time * Performance-critical paths where heap allocation must be avoided * Interfacing with APIs that expect contiguous memory but still want type safety * Embedded or low-level systems where predictability matters I’m curious — do you actively use std::array, or does it also fall into that “I know it, but rarely use it” category for you? #cpp #cplusplus #softwareengineering #systemprogramming #embeddedsystems #stl #coding #developers #programming
To view or add a comment, sign in
-
-
Hi folks, I was building a personal project this weekend and ended up using a lot of smart pointers in C++. Ive noticed that many people find them confusing at first, so here’s a simple way I think about them: 1. std::unique_ptr Use this when there is clear, single ownership. The object’s lifetime is tied to one owner, and ownership can be transferred using std::move. 2. std::shared_ptr Use this when multiple parts of your system need to share ownership of an object. The object lives until the last reference is released, preventing premature deletion. Be careful though cyclic references can lead to memory leaks. 3. std::weak_ptr A non-owning reference to an object managed by shared_ptr. It does not affect the object’s lifetime and is mainly used to break cyclic dependencies. Still exploring more real-world patterns around this. Would love to hear how others approach this. #cpp #multithreading #systemsprogramming
To view or add a comment, sign in
-
I used to add std::move everywhere to "optimise" my C++. Turns out... I was sometimes making things slower. Two surprising cases: 1. It can block compiler optimisations. For instance, this: return std::move(local); can prevent Named Return Value Optimisation (NRVO/RVO) because it forces the compiler to treat local as an rvalue, preventing it from eliding the copy/move entirely. So instead of zero-cost, I was forcing an extra move. 2. It is pointless for small types. For trivially copyable types, moving is effectively the same as copying. Example: struct Point { int x,y; } Point a{1,2}; Point b = std::move(a); //no real gain since a is effectively copied We are not saving anything here; in fact, it could potentially add extra noise. One big takeaway for me is: std::move is not an optimisation, it is more of a signal. It tells the compiler "I am done with the object, you can steal its resources". So now, I only use it when it actually matters, such as types that own heap memory. What surprised you most about std::move when you learned it properly? #CPlusPlus #optimization #moderncpp
To view or add a comment, sign in
-
🚀 uint32_t vs unsigned int — What’s the difference? If you're writing embedded code, knowing the difference is important. Here’s a simple breakdown 👇 🔹 uint32_t → Defined in "stdint.h" and always 32-bit 🔹 unsigned int → Built-in C type, size can depend on compiler 💡 Simple rule: Need exact 32 bits? Use uint32_t General use? unsigned int can work. ✅ Use uint32_t for: - Registers - CAN/SPI/UART data - Portable code ✅ Use unsigned int for: - Counters - General variables ⚠️ When size matters → use uint32_t Small difference… but important in embedded C. #EmbeddedSystems #CProgramming #Firmware #STM32 #EmbeddedC
To view or add a comment, sign in
-
Mutex might sound like the solution here, but you also essentially lose the parallelism by making the thread wait for other threads to finish work. Things LIKE atomics should be considered the defacto answer, mutexes are a last resort.
Debugging a Race Condition in C++ While working on a multithreaded module, I encountered an unexpected issue. Even though the logic looked correct, the final output was inconsistent every time. Problem: Multiple threads were updating a shared variable without synchronization. Expected: 200000 Actual: Random incorrect values After debugging, I found the root cause: Race Condition due to non-atomic operation (counter++) Key Learning: In multithreading, even a simple increment operation is not safe. It involves: Read → Modify → Write When multiple threads execute this simultaneously, data gets corrupted. Solution: Used mutex to synchronize access to shared resource. Also improved code using: lock_guard<mutex> for better safety and readability. Takeaway: Never trust shared data in multithreaded environments without proper synchronization. #cpp #multithreading #racecondition #concurrency #debugging
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development