C++ Smart Pointers and Arrays (2023)

C++ Smart Pointers and Arrays (1)

Smart pointers are very versatile and can hold pointers not only to single instances but also to arrays. Is that only a theoretical use case? or maybe they might be handy in some cases? Let’s have a look.

Smart pointers for T[]

At C++ Stories, you can find lots of information about smart pointers - see this separate tag for this area. For completeness, I’d like to mention an interesting issue on smart pointers and arrays.

If you want to create a unique_ptr, you can write:

class Object { };// unique_ptrauto ptr = std::make_unique<Object>();auto intPtr = std::make_unique<int>();// or shared_ptrauto shared = std::make_shared<Object>();auto intShared = std::make_shared<int>();

In the example, you see pointers to a single instance of Object or an integer.

Similarly, if you want to have a pointer to an array of objects then you’re happy to do it in C++:

auto objects = std::make_unique<Object[]>(10);auto ptr = std::make_unique<int[]>(10);std::cout << ptr[0] << '\n';std::cout << ptr[9] << '\n'; 

In the above example, make_unique returns a pointer to an array of 10 elements.

The specialization for T[] for unique_ptr is supported since C++11, but make_unique for arrays is available since C++14.

And for shared pointers:

auto shared = std::make_shared<int[]>(10);std::cout << shared[0] << '\n';std::cout << shared[9] << '\n';
The specialization for T[] for shared_ptr is supported since C++17, but make_shared for arrays is available since C++20.

If your compiler doesn’t support make_shared<T[]> you can write:

(Video) SMART POINTERS in C++ (std::unique_ptr, std::shared_ptr, std::weak_ptr)

std::shared_ptr<int[]> shared(new int[10]());

Play with code @Compiler Explorer

But be warned! The following code will also work:

std::shared_ptr<int> shared(new int[10]());

But what happens when the memory is about to be deleted? Will the proper delete operator will be called?

That’s why it’s essential to make sure the pointer’s declaration matches the initializing expression.

Improvements in C++20

In C++20, we have a bunch of new functions with the suffix _for_overwrite. In short, they create arrays without performing value initialization. Compare this code:

new T[]()// vsnew T[]
  • The first is “value initialization.” For arrays, initialize each element to zero (for built-in types) or call their default ctors.
  • The latter is called default initialization and, for built-in types, generates indeterminate values or calls default ctor.

make_unique uses the first option, while make_unique_for_overwrite uses the second approach.

auto ptr = std::make_unique_for_overwrite<int[]>(COUNT);

And after that line, the values inside ptr are indeterminate, so you should make sure you initialize buffer later.

Would you like to see more?
The _for_overwrite functions allow for even 20x init speed up of the initialization code! See my premium article with a benchmark which is available for C++ Stories Premium/Patreon members. See all Premium benefits here.

(Video) C++ POINTERS (2020) - How to use pointers and arrays (for beginners) PROGRAMMING TUTORIAL

Ok, we covered how to create pointers and even saw some recent updates in C++20… but should we even use it?

How about using a proper container?

I guess it’s much more convenient to use std::vector<int> and pass it around than passing unique_ptr<int[]>?

Let’s have a look at some possible use cases.

Why is unique_ptr<T[]> useful?

When I wrote my early blog post on smart pointers - C++ Smart Pointers Gotchas - C++ Stories, back in 2013, I also asked a question at Stack Overflow.

c++ - Is there any use for unique_ptr with array? - Stack Overflow

C++ Smart Pointers and Arrays (2)

And so far, it’s one of my most voted questions :)

I got several interesting answers, and we can summarize them with the following quote:

Some people do not have the luxury of using std::vector, even with allocators. Some people need a dynamically sized array, so std::array is out. And some people get their arrays from other code that is known to return an array; and that code isn’t going to be rewritten to return a vector or something.

And here’s a nice comparison for each technique:

(Video) CppCon 2019: Arthur O'Dwyer “Back to Basics: Smart Pointers”

Use casestd::arraystd::vectorstd::unique_ptr<T[]>
Initial sizethe size to be specified at compile timeruntimeruntime
Resizingdoes not allow resizingcan grow, shrink, changedoes not allow resizing (unless you recreate the whole thing)
Storagestores data directly in the objectoutside, usually on the heapoutside, usually on the heap
Copyingallows copyingallows copyingdoes not allow
Swap/moveO(n) time swap and move operations, where n is the number of elements in the arrayO(1) time swap and move operationsO(1) time swap and move operations
Pointer/reference/iterator invalidationensures pointers, references and iterators will never be invalidated while the object is live, even on swap()vector may invalidate pointers and iterators when you have a reallocationhas no pointers, iterators, so you can only invalidate it by swap
Compatibility with concepts and algorithmsis a regular containeris a regular containeris not a container, so it doesn’t work with standard algorithms(*)

Update on algorithms

(*) update: unique_ptr<T[]> is not a container, so it won’t work with standard algorithms… at least out of the box. But you can get the pointer to the array and since a pointer is an iterator, you can pass it into an algorithm.

Pointed out by this comment at r/cpp.

Have a look:

auto ptr = std::make_unique<int[]>(10);// init elements...std::sort(ptr.begin(), ptr.end()); // compiler error! p is not a container// but this worksstd::sort(ptr.get(), ptr.get() + COUNT, ...);

See more code:

std::random_device rd;std::mt19937 g(rd());auto print = [](int* p, size_t count) { for (size_t i = 0; i < count; ++i) std::cout << p[i] << ", "; std::cout << "\n";};const size_t COUNT = 10;auto ptr = std::make_unique<int[]>(COUNT);std::iota(ptr.get(), ptr.get() + COUNT, 0);print(ptr.get(), COUNT);std::shuffle(ptr.get(), ptr.get() + COUNT, g);print(ptr.get(), COUNT);std::sort(ptr.get(), ptr.get() + COUNT);print(ptr.get(), COUNT);

Play with code @Compiler Explorer

But is that “natural”?

Why handy?

In summary, I’d say that smart pointers for arrays are handy in two cases:

  • When you want to have complete control over the memory block. Standard containers might reallocate internal buffers, and your requirements and restrictions might not allow that. For example, when you’re in a hot path or some embedded environment.
  • To interoperate with C-Style APIs. Usually, such functions require raw pointers, and sometimes it might be more convenient to use a smart pointer to array.

Let’s have a look at some real-life stories.

Use Cases

Here’s what we can read in the comments and answers:

Memory-pool

I have used unique_ptr<char[]> to implement preallocated memory pools used in a game engine.

(Video) smart pointers and arrays - C++

connecting with C-style functions

A common pattern can be found in some Windows Win32 API calls, in which the use of std::unique_ptr<T[]>

As an alternative to vector<bool>

I faced a case where I had to use std::unique_ptr<bool[]>, which was in the HDF5 library (A library for efficient binary data storage, used a lot in science). Some compilers (Visual Studio 2015 in my case) provide compression of std::vector (by using 8 bools in every byte), which is a catastrophe for something like HDF5, which doesn’t care about that compression. With std::vector<bool>, HDF5 was eventually reading garbage because of that compression. Guess who was there for the rescue, in a case where std::vector didn’t work, and I needed to allocate a dynamic array cleanly? :-)

If you're interested in smart pointers - have a look at my handy reference card. It covers everything you need to know about unique_ptr, shared_ptr and weak_ptr, wrapped in a beautiful PDF:

Summary

In this blog post, we had a look at ways to create and initialize smart pointers for arrays. You also learned that in C++20, we have a set of functions for skipping the value initialization part to achieve better performance.

Are such pointers helpful?

While they might have limited use, as it’s usually better to rely on standard containers, they might be handy in restricted environments. For example, when you want complete control over the memory buffer and when you interop with C-style API.

We can also summarize it with a quote from Effective Modern C++ by Scott Meyers

The existence of std::unique_ptr for arrays should be of only intellectual interest to you, because std::array, std::vector, std::string are virtually always better data structure choices than raw arrays. About the only situation I can conceive of when a std::unique_ptr<T[]> would make sense would be when you’re using a C-like API that returns a raw pointer to a heap array that you assume ownership of.

Back to you

Have you used smart pointers for arrays?

(Video) SMART POINTERS in C++ (for beginners in 20 minutes)

Share your story in the comments below the article.

FAQs

What is a smart pointer in C++? ›

Smart pointers are objects which store pointers to dynamically allocated (heap) objects. They behave much like built-in C++ pointers except that they automatically delete the object pointed to at the appropriate time.

Does C ++ 11 have smart pointers? ›

Introduction of Smart Pointers

C++11 comes up with its own mechanism that's Smart Pointer. When the object is destroyed it frees the memory as well. So, we don't need to delete it as Smart Pointer does will handle it.

Are smart pointers on the stack or heap? ›

As shown in the example, a smart pointer is a class template that you declare on the stack, and initialize by using a raw pointer that points to a heap-allocated object.

Why should you use smart pointers instead of regular pointers? ›

Smart pointers try to prevent memory leaks by making the resource deallocation automatic: when the pointer to an object (or the last in a series of pointers) is destroyed, for example because it goes out of scope, the pointed object is destroyed too. Save this answer.

What are smart pointers good for? ›

Smart pointers are used to make sure that an object is deleted if it is no longer used (referenced). The unique_ptr<> template holds a pointer to an object and deletes this object when the unique_ptr<> object is deleted.

How many types of smart pointers are there in C++? ›

The three types of smart pointers, as of C++11, are listed as follows: std::unique_ptr. std::shared_ptr. std::weak_ptr.

Should I use unique_ptr or shared_ptr? ›

Use unique_ptr when you want to have single ownership(Exclusive) of the resource. Only one unique_ptr can point to one resource. Since there can be one unique_ptr for single resource its not possible to copy one unique_ptr to another. A shared_ptr is a container for raw pointers.

When were smart pointers introduced to C++? ›

Smart pointers were first popularized in the programming language C++ during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection.

Why Auto_ptr is deprecated? ›

auto_ptr cannot be used in STL containers because it has a copy constructor that does not meet requirements of container CopyConstructible. unique_ptr does not implement a copy constructor, so containers use alternate methods. unique_ptr can be used in containers and is faster for std algorithms than shared_ptr.

How are smart pointers implemented in C++? ›

Smart pointer in C++, can be implemented as template class, which is overloaded with * and -> operator. auto_ptr, shared_ptr, unique_ptr and weak_ptr are the forms of smart pointer can be implemented by C++ libraries.

What is weak pointer in C++? ›

(since C++11) std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

What is the use of pointers C++? ›

Pointers are used extensively in both C and C++ for three main purposes: to allocate new objects on the heap, to pass functions to other functions. to iterate over elements in arrays or other data structures.

Should I ever use raw pointers? ›

Rust has a number of different smart pointer types in its standard library, but there are two types that are extra-special. Much of Rust's safety comes from compile-time checks, but raw pointers don't have such guarantees, and are unsafe to use.

What is ownership in C++? ›

An owner is an object containing a pointer to an object allocated by new for which a delete is required. Every object on the free store (heap, dynamic store) must have exactly one owner. If there are two pointers to an object on the free store, only one can be the owner.

How do you create a unique pointer in C++? ›

auto ptr = make_unique<int>(); // Create a new unique_ptr object. auto ptr = make_unique<int>(); The dynamically allocated object is destroyed when the created unique pointer object is destroyed.

Are pointers smart? ›

Pointers are good-natured dogs who love spending time hunting or playing with their families. They are alert and energetic, but they also have a calm, self-possessed quality. Pointers are smart and take well to training. They have a touch of wanderlust, so walking them on a leash is imperative.

Do you need a destructor with smart pointers? ›

Boost smart pointers by themselves don't have anything to do with the need for a destructor. All they do is remove the need for you to call delete on the allocated memory that they are effectively managing.

What is polymorphism C++? ›

Polymorphism means "many forms", and it occurs when we have many classes that are related to each other by inheritance. Like we specified in the previous chapter; Inheritance lets us inherit attributes and methods from another class. Polymorphism uses those methods to perform different tasks.

Does C++ have garbage collection? ›

A C++ program can contain both manual memory management and garbage collection happening in the same program. According to the need, either the normal pointer or the specific garbage collector pointer can be used. Thus, to sum up, garbage collection is a method opposite to manual memory management.

What is the difference between shared_ptr and Weak_ptr? ›

The only difference between weak_ptr and shared_ptr is that the weak_ptr allows the reference counter object to be kept after the actual object was freed. As a result, if you keep a lot of shared_ptr in a std::set the actual objects will occupy a lot of memory if they are big enough.

Is shared_ptr thread safe? ›

std::shared_ptr is not thread safe. A shared pointer is a pair of two pointers, one to the object and one to a control block (holding the ref counter, links to weak pointers ...).

Can a Weak_ptr point to a unique_ptr? ›

You can implement weak_ptr which works correctly with unique_ptr but only on the same thread - lock method will be unnecessary in this case.

Why auto_ptr Cannot be used with STL? ›

This is because auto_ptr has semantics of strict ownership and is thus solely responsible for an object during the object's life cycle. If we copy the auto_ptr then the source auto_ptr will lose the reference to the underlying object.

What is Make_shared in C++? ›

It constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it.

What is Autoptr in C++? ›

auto_ptr is a class template that was available in previous versions of the C++ standard library (declared in the <memory> header file), which provides some basic RAII features for C++ raw pointers. It has been replaced by the unique_ptr class.

What is boost :: shared_ptr? ›

shared_ptr is now part of the C++11 Standard, as std::shared_ptr . Starting with Boost release 1.53, shared_ptr can be used to hold a pointer to a dynamically allocated array. This is accomplished by using an array type ( T[] or T[N] ) as the template parameter.

When should I use weak pointer? ›

A weak pointer is a smart pointer that does not take ownership of an object but act as an observer. In other words, it does not participate in reference counting to delete an object or extend its lifetime. Weak pointers are mainly used to break the circular dependency that shared pointers create.

What do you mean by dangling pointer? ›

Dangling pointers and wild pointers in computer programming are pointers that do not point to a valid object of the appropriate type. These are special cases of memory safety violations. More generally, dangling references and wild references are references that do not resolve to a valid destination.

Is Weak_ptr thread safe? ›

Note that the control block used by std::weak_ptr and std::shared_ptr is thread-safe: different non-atomic std::weak_ptr objects can be accessed using mutable operations, such as operator= or reset , simultaneously by multiple threads, even when these instances are copies or otherwise share the same control block ...

Why the usage of pointers in C++ is not recommended? ›

It is best to avoid using pointers in C++ as much as possible. The use of pointers can lead to confusion of ownership which can directly or indirectly lead to memory leaks. Even if object ownership is well managed simple (and difficult to find) bugs can also lead to memory leaks.

What are the disadvantages of pointers? ›

Disadvantages of pointers:- 1)we can access the restricted memory area. 2) Pointers require one additional dereference, meaning that the final code must read the variable's pointer from memory, then read the variable from the pointed-to memory. This is slower than reading the value directly from memory.

What is an array in C++? ›

Arrays are used to store multiple values in a single variable, instead of declaring separate variables for each value. To declare an array, define the variable type, specify the name of the array followed by square brackets and specify the number of elements it should store: string cars[4];

Is it OK to use raw pointers in C++? ›

Getting the obvious out of the way, yes, the conventional wisdom is "don't use raw pointers in modern C++". if that parallel_for is executing on CPU all is fine, but will fail on GPU. If you use std::vector here it will fail at runtime.

When should you use raw pointers in C++? ›

Pointers (along with references) are used extensively in C++ to pass larger objects to and from functions. It's often more efficient to copy an object's address than to copy the entire object. When defining a function, specify pointer parameters as const unless you intend the function to modify the object.

Does STD move transfer ownership? ›

In C++11 we can transfer the ownership of an object to another unique_ptr using std::move() . After the ownership transfer, the smart pointer that ceded the ownership becomes null and get() returns nullptr.

Who is C++ developer? ›

C++ (pronounced "C plus plus") is a high-level general-purpose programming language created by Danish computer scientist Bjarne Stroustrup as an extension of the C programming language, or "C with Classes".

What is ownership in Pointer? ›

Ownership means “responsibility to cleanup”. The owner of the memory is the one who has to delete its pointer. Deletion can either be explicit (through the keyword delete of the function free() regarding raw pointers) or bound to the lifetime of an object (through smart pointers and RAII1).

Can two unique pointers point to same address? ›

Pointers: Pointing to the Same Address

There is no limit on the number of pointers that can hold (and therefore point to) the same address.

Can you copy a unique pointer? ›

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.

What is a unique_ptr in C++? ›

(since C++11) std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.

How do you write a smart pointer in C++? ›

Smart pointers
  1. #include <iostream>
  2. using namespace std;
  3. class SmartPtr { // Create the class to implement smart Pointer.
  4. int* ptr; // Actual pointer.
  5. public:
  6. // Create an explicit constructor.
  7. explicit SmartPtr(int* p = NULL) { ptr = p; }
  8. // Destructor to deallocate the resource used.

What is a Weak_ptr? ›

std::weak_ptr is a smart pointer that holds a non-owning ("weak") reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.

Why Auto_ptr is deprecated? ›

auto_ptr cannot be used in STL containers because it has a copy constructor that does not meet requirements of container CopyConstructible. unique_ptr does not implement a copy constructor, so containers use alternate methods. unique_ptr can be used in containers and is faster for std algorithms than shared_ptr.

When were smart pointers introduced to C++? ›

Smart pointers were first popularized in the programming language C++ during the first half of the 1990s as rebuttal to criticisms of C++'s lack of automatic garbage collection.

What are the different types of smart pointers? ›

C++ libraries provide implementations of smart pointers in following types: auto_ptr.

What is the use of pointers C++? ›

Pointers are used extensively in both C and C++ for three main purposes: to allocate new objects on the heap, to pass functions to other functions. to iterate over elements in arrays or other data structures.

What is the purpose of unique pointer C++? ›

Unique pointers are smart pointers that help us in memory management. Unique pointers guarantee they delete their object if they are destructed, therefore, one less hassle for programmers.

Why weak pointer is used? ›

By using a weak_ptr , you can create a shared_ptr that joins to an existing set of related instances, but only if the underlying memory resource is still valid. A weak_ptr itself does not participate in the reference counting, and therefore, it cannot prevent the reference count from going to zero.

What is a weak reference in C++? ›

In computer programming, a weak reference is a reference that does not protect the referenced object from collection by a garbage collector, unlike a strong reference.

What is Make_shared in C++? ›

It constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr that owns and stores a pointer to it.

Why auto_ptr Cannot be used with STL? ›

This is because auto_ptr has semantics of strict ownership and is thus solely responsible for an object during the object's life cycle. If we copy the auto_ptr then the source auto_ptr will lose the reference to the underlying object.

What is Autoptr in C++? ›

auto_ptr is a class template that was available in previous versions of the C++ standard library (declared in the <memory> header file), which provides some basic RAII features for C++ raw pointers. It has been replaced by the unique_ptr class.

What is shared_ptr? ›

std::shared_ptr is a smart pointer that retains shared ownership of an object through a pointer. Several shared_ptr objects may own the same object.

Videos

1. Back to Basics: Smart Pointers - Rainer Grimm - CppCon 2020
(CppCon)
2. Back to Basics: Smart Pointers and RAII - Inbal Levi - CppCon 2021
(CppCon)
3. C++ Tutorial | Part 33 | Pointers and arrays of class objects
(Suraj Sharma)
4. Back to Basics: Pointers - Mike Shah - CppCon 2021
(CppCon)
5. C++ POINTERS FULL COURSE Beginner to Advanced (Learn C++ Pointers in 2,5 hours)
(CodeBeauty)
6. C++ Tutorial 15 : Smart Pointers & Polymorphic Templates
(Derek Banas)
Top Articles
Latest Posts
Article information

Author: Gov. Deandrea McKenzie

Last Updated: 12/30/2022

Views: 6131

Rating: 4.6 / 5 (46 voted)

Reviews: 85% of readers found this page helpful

Author information

Name: Gov. Deandrea McKenzie

Birthday: 2001-01-17

Address: Suite 769 2454 Marsha Coves, Debbieton, MS 95002

Phone: +813077629322

Job: Real-Estate Executive

Hobby: Archery, Metal detecting, Kitesurfing, Genealogy, Kitesurfing, Calligraphy, Roller skating

Introduction: My name is Gov. Deandrea McKenzie, I am a spotless, clean, glamorous, sparkling, adventurous, nice, brainy person who loves writing and wants to share my knowledge and understanding with you.