cppreference.com

Std::unique_ptr<t,deleter>:: operator=.

(C++20)
(C++20)
(C++11)
(C++20)
(C++17)
(C++11)
(C++11)
(basic types, RTTI)
(C++20)
(C++20)
Three-way comparison (C++20)
three_way_comparable_with (C++20)
   
is_neqis_ltis_lteqis_gtis_gteq (C++20)(C++20)(C++20)(C++20)(C++20)
General utilities
(C++20)
Relational operators (deprecated in C++20)
rel_ops::operator>
rel_ops::operator>=
cmp_lesscmp_less_than (C++20)(C++20)   
cmp_greatercmp_greater_than (C++20)(C++20)
Allocators
  
Memory resources
Uninitialized storage
Uninitialized memory algorithms
  
(until C++23)
(until C++23)
(until C++23)
Miscellaneous
Member functions
Modifiers
Observers
unique_ptr::operator->
Non-member functions
make_unique_for_overwrite (C++20)
operator!=operator<operator>operator<=operator>=operator<=> (until C++20)(C++20)
operator=( unique_ptr&& r ) noexcept; (1) (constexpr since C++23)
< class U, class E >
unique_ptr& operator=( unique_ptr<U,E>&& r ) noexcept;
(2) (constexpr since C++23)
operator=( ) noexcept; (3) (constexpr since C++23)
operator=( unique_ptr&& r ) noexcept; (1) (constexpr since C++23)
< class U, class E >
unique_ptr& operator=( unique_ptr<U,E>&& r ) noexcept;
(2) (constexpr since C++23)
operator=( ) noexcept; (3) (constexpr since C++23)

If Deleter is not a reference type, requires that it is nothrow- MoveAssignable . If Deleter is a reference type, requires that std:: remove_reference < Deleter > :: type is nothrow- CopyAssignable .

  • This assignment operator of the primary template only participates in overload resolution if U is not an array type and unique_ptr < U,E > :: pointer is implicitly convertible to pointer and std:: is_assignable < Deleter & , E && > :: value is true .
  • This assignment operator in the specialization for arrays, std::unique_ptr<T[]> behaves the same as in the primary template, except that will only participate in overload resolution if all of the following is true:
  • U is an array type
  • pointer is the same type as element_type*
  • unique_ptr<U,E>::pointer is the same type as unique_ptr<U,E>::element_type*
  • unique_ptr<U,E>::element_type(*)[] is convertible to element_type(*)[]
  • std:: is_assignable < Deleter & , E && > :: value is true

Note that unique_ptr 's assignment operator only accepts rvalues , which are typically generated by std::move . (The unique_ptr class explicitly deletes its lvalue copy constructor and lvalue assignment operator.)

Parameters Return value Example Defect reports

[ edit ] Parameters

r - smart pointer from which ownership will be transferred

[ edit ] Return value

[ edit ] example, [ edit ] defect reports.

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
C++11 rejected qualification conversions accepts
C++11 the converting assignment operator was not constrained constrained
C++11 the move assignment operator was not constrained constrained
  • Recent changes
  • Offline version
  • What links here
  • Related changes
  • Upload file
  • Special pages
  • Printable version
  • Permanent link
  • Page information
  • In other languages
  • This page was last modified on 13 April 2022, at 08:00.
  • This page has been accessed 280,042 times.
  • Privacy policy
  • About cppreference.com
  • Disclaimers

Powered by MediaWiki

22.5 — std::unique_ptr

The compiler is given a lot of flexibility in terms of how it handles this call. It could create a new T, then call function_that_can_throw_exception(), then create the std::unique_ptr that manages the dynamically allocated T. If function_that_can_throw_exception() throws an exception, then the T that was allocated will not be deallocated, because the smart pointer to do the deallocation hasn’t been created yet. This leads to T being leaked.

In the above code, createResource() returns a std::unique_ptr by value. If this value is not assigned to anything, the temporary return value will go out of scope and the Resource will be cleaned up. If it is assigned (as shown in main()), in C++14 or earlier, move semantics will be employed to transfer the Resource from the return value to the object assigned to (in the above example, ptr), and in C++17 or newer, the return will be elided. This makes returning a resource by std::unique_ptr much safer than returning raw pointers!

This browser is no longer supported.

Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.

unique_ptr Class

  • 8 contributors

Stores a pointer to an owned object or array. The object/array is owned by no other unique_ptr . The object/array is destroyed when the unique_ptr is destroyed.

Right A unique_ptr .

Nptr An rvalue of type std::nullptr_t .

Ptr A pointer .

Deleter A deleter function that is bound to a unique_ptr .

No exceptions are generated by unique_ptr .

The unique_ptr class supersedes auto_ptr , and can be used as an element of C++ Standard Library containers.

Use the make_unique helper function to efficiently create new instances of unique_ptr .

unique_ptr uniquely manages a resource. Each unique_ptr object stores a pointer to the object that it owns or stores a null pointer. A resource can be owned by no more than one unique_ptr object; when a unique_ptr object that owns a particular resource is destroyed, the resource is freed. A unique_ptr object may be moved, but not copied; for more information, see Rvalue Reference Declarator: && .

The resource is freed by calling a stored deleter object of type Del that knows how resources are allocated for a particular unique_ptr . The default deleter default_delete<T> assumes that the resource pointed to by ptr is allocated with new , and that it can be freed by calling delete _Ptr . (A partial specialization unique_ptr<T[]> manages array objects allocated with new[] , and has the default deleter default_delete<T[]> , specialized to call delete[] ptr .)

The stored pointer to an owned resource, stored_ptr has type pointer . It's Del::pointer if defined, and T * if not. The stored deleter object stored_deleter occupies no space in the object if the deleter is stateless. Note that Del can be a reference type.

Constructors

Name Description
There are seven constructors for .
Name Description
A synonym for the template parameter .
A synonym for the template parameter .
A synonym for if defined, otherwise .
Name Description
Returns .
Returns a reference to .
stores in and returns its previous contents.
Releases the currently owned resource and accepts a new resource.
Exchanges resource and with the provided .
Name Description
The operator returns a value of a type that is convertible to . The result of the conversion to is when , otherwise .
The member function returns .
The member function returns .
Assigns the value of a (or a ) to the current .

deleter_type

The type is a synonym for the template parameter Del .

element_type

The type is a synonym for the template parameter Type .

The type is a synonym for the template parameter Ty .

Returns stored_ptr .

The member function returns stored_ptr .

get_deleter

Returns a reference to stored_deleter .

The member function returns a reference to stored_deleter .

Assigns the address of the provided unique_ptr to the current one.

A unique_ptr reference used to assign the value of to the current unique_ptr .

The member functions call reset(right.release()) and move right.stored_deleter to stored_deleter , then return *this .

A synonym for Del::pointer if defined, otherwise Type * .

The type is a synonym for Del::pointer if defined, otherwise Type * .

Releases ownership of the returned stored pointer to the caller and sets the stored pointer value to nullptr .

Use release to take over ownership of the raw pointer stored by the unique_ptr . The caller is responsible for deletion of the returned pointer. The unique-ptr is set to the empty default-constructed state. You can assign another pointer of compatible type to the unique_ptr after the call to release .

This example shows how the caller of release is responsible for the object returned:

Takes ownership of the pointer parameter, and then deletes the original stored pointer. If the new pointer is the same as the original stored pointer, reset deletes the pointer and sets the stored pointer to nullptr .

ptr A pointer to the resource to take ownership of.

Use reset to change the stored pointer owned by the unique_ptr to ptr and then delete the original stored pointer. If the unique_ptr wasn't empty, reset invokes the deleter function returned by get_deleter on the original stored pointer.

Because reset first stores the new pointer ptr , and then deletes the original stored pointer, it's possible for reset to immediately delete ptr if it's the same as the original stored pointer.

Exchanges pointers between two unique_ptr objects.

right A unique_ptr used to swap pointers.

The member function swaps stored_ptr with right.stored_ptr and stored_deleter with right.stored_deleter .

There are seven constructors for unique_ptr .

ptr A pointer to the resource to be assigned to a unique_ptr .

_Deleter A deleter to be assigned to a unique_ptr .

right An rvalue reference to a unique_ptr from which unique_ptr fields are move assigned to the newly constructed unique_ptr .

The first two constructors construct an object that manages no resource. The third constructor stores ptr in stored_ptr . The fourth constructor stores ptr in stored_ptr and deleter in stored_deleter .

The fifth constructor stores ptr in stored_ptr and moves deleter into stored_deleter . The sixth and seventh constructors store right.release() in stored_ptr and moves right.get_deleter() into stored_deleter .

~unique_ptr

The destructor for unique_ptr , destroys a unique_ptr object.

The destructor calls get_deleter()(stored_ptr) .

Was this page helpful?

Additional resources

Understanding unique_ptr with Example in C++11

The smart pointers are a really good mechanism to manage dynamically allocated resources. In this article, we will see unique_ptr with example in C++11. But we don’t discuss standard smart pointers from a library. Rather, we implement our own smart pointer equivalent to it. This will give us an idea of inside working of smart pointers.

Prior to C++11, the standard provided std::auto_ptr . Which had some limitations. But from C++11, standard provided many smart pointers classes. Understanding unique_ptr with example in C++ requires an understanding of move semantics which I have discussed here & here .

But before all these nuisances, we will see “Why do we need smart pointer in 1st place?”:

Why do we need smart pointers? #

func() { Resource *ptr = new Resource; int x; std::cout << "Enter an integer: "; std::cin >> x; if (x == 0) throw 0; // the function returns early, and ptr won't be deleted! if (x < 0) return; // the function returns early, and ptr won't be deleted! // do stuff with ptr here delete ptr; }
  • In the above code, the early return or throw statement, causing the function to terminate without variable ptr being deleted.
  • Consequently, the memory allocated for variable ptr is now leaked (and leaked again every time this function is called and returns early).
  • These kinds of issues occur because pointer variables have no inherent mechanism to clean up after themselves.
  • Following class cleans-up automatically when sources are no longer in use:

smart_ptr aka std::auto_ptr from C++98 #

<class T> class smart_ptr { T* m_ptr; public: smart_ptr(T* ptr=nullptr):m_ptr(ptr){} ~smart_ptr() { delete m_ptr; } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } };
  • Now, let’s go back to our func() example above, and show how a smart pointer class can solve our challenge:
Resource { public: Resource() { std::cout << "Resource acquired\n"; } ~Resource() { std::cout << "Resource destroyed\n"; } }; void func() { smart_ptr<Resource> ptr(new Resource); // ptr now owns the Resource int x; std::cout << "Enter an integer: "; std::cin >> x; if (x == 0) throw 0; if (x < 0) return; // do stuff with ptr here // dont care about deallocation } int main() { try{ func(); } catch(int val){} return 0; }
Hi! Resource destroyed
  • Note that even in the case where the user enters zero and the function terminates early, the Resource is still properly deallocated.
  • Because of the ptr variable is a local variable. ptr destroys when the function terminates (regardless of how it terminates). And because of the smart_ptr destructor will clean up the Resource , we are assured that the Resource will be properly cleaned up.
  • There is still some problem with our code. Like:
main() { smart_ptr<Resource> res1(new Resource); smart_ptr<Resource> res2(res1); // Alternatively, don't initialize res2 and then assign res2 = res1; return 0; }
Resource destroyed Resource destroyed
  • In this case destructor of our Resource object will be called twice which can crash the program.
  • What if, instead of having our copy constructor and assignment operator copy the pointer (“copy semantics”), we instead transfer/move ownership of the pointer from the source to the destination object? This is the core idea behind move semantics. Move semantics means the class will transfer ownership of the object rather than making a copy.
  • Let’s update our smart_ptr class to show how this can be done:
<class T> class smart_ptr { T* m_ptr; public: smart_ptr(T* ptr=nullptr) :m_ptr(ptr) {} ~smart_ptr() { delete m_ptr; } // copy constructor that implements move semantics smart_ptr(smart_ptr& a) // note: not const { m_ptr = a.m_ptr; // transfer our dumb pointer from the source to our local object a.m_ptr = nullptr; // make sure the source no longer owns the pointer } // assignment operator that implements move semantics smart_ptr& operator=(smart_ptr& a) // note: not const { if (&a == this) return *this; delete m_ptr; // make sure we deallocate any pointer the destination is already holding first m_ptr = a.m_ptr; // then transfer our dumb pointer from the source to the local object a.m_ptr = nullptr; // make sure the source no longer owns the pointer return *this; } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } }; class Resource { public: Resource() { std::cout << "Resource acquired\n"; } ~Resource() { std::cout << "Resource destroyed\n"; } }; int main() { smart_ptr<Resource> res1(new Resource); smart_ptr<Resource> res2(res1); return 0; }
Resource destroyed

std::auto_ptr , and why to avoid it #

  • What we have seen above as smart_ptr is basically an std::auto_ptr which was introduced in C++98, was C++’s first attempt at a standardized smart pointer.
  • However, std::auto_ptr (and our smart_ptr class) has a number of problems that make using it dangerous.
  • Because std::auto_ptr implements move semantics through the copy constructor and assignment operator, passing an std::auto_ptr by value to a function will cause your resource to get moved to the function parameter (and be destroyed at the end of the function when the function parameters go out of scope). Then when you go to access your std::auto_ptr argument from the caller (not realizing it was transferred and deleted), you’re suddenly dereferencing a null pointer. Crash!
  • std::auto_ptr always deletes its contents using non-array delete. This means std::auto_ptr won’t work correctly with dynamically allocated arrays, because it uses the wrong kind of deallocation. Worse, it won’t prevent you from passing it a dynamic array, which it will then mismanage, leading to memory leaks.
  • Because of the above-mentioned shortcomings, std::auto_ptr has been deprecated in C++11, and it should not used. In fact, std::auto_ptr slated for complete removal from the standard library as part of C++17!
  • Overriding the copy semantics to implement move semantics leads to weird edge cases and inadvertent bugs. Because of this, in C++11, the concept of “move” formally defined. And “move semantics” added to the language to properly differentiate copying from moving. In C++11, std::auto_ptr has been replaced by a bunch of other types of “move-aware” smart pointers: std::scoped_ptr , std::unique_ptr , std::weak_ptr , and std::shared_ptr .
  • We’ll also explore the two most popular of these: std::unique_ptr (which is a direct replacement for std::auto_ptr ) and std::shared_ptr .

std::unique_ptr with example in C++11 #

  • std::unique_ptr is the C++11 replacement for std::auto_ptr . It is used to manage use to manage any dynamically allocated object not shared by multiple objects. That is, std::unique_ptr should completely own the object it manages, not share that ownership with other classes.
  • We can convert our smart_ptr we designed above into std::unique_ptr . And for that one thing, we can do is delete the copy constructor & assignment operator so that no one can copy smart pointer.
  • As we are not allowing a copy of smart pointer we can’t pass our smart pointer to any function by value or return by value. And this is not good design.
  • To pass or return by value, we can add move constructor & move assignment operator, so that while passing or returning by value, we would have to transfer ownership through move semantics. This way we can also ensure single ownership throughout the lifetime of the object.
<class T> class smart_ptr { T* m_ptr; public: smart_ptr(T* ptr = nullptr) : m_ptr(ptr){} ~smart_ptr() { delete m_ptr; } // Copy constructor smart_ptr(const smart_ptr& a) = delete; // Move constructor smart_ptr(smart_ptr&& a) : m_ptr(a.m_ptr) { a.m_ptr = nullptr; } // Copy assignment smart_ptr& operator=(const smart_ptr& a) = delete; // Move assignment smart_ptr& operator=(smart_ptr&& a) { if (&a == this) return *this; delete m_ptr; m_ptr = a.m_ptr; a.m_ptr = nullptr; return *this; } T& operator*() const { return *m_ptr; } T* operator->() const { return m_ptr; } }; class Resource { public: Resource() { std::cout << "Resource acquired\n"; } ~Resource() { std::cout << "Resource destroyed\n"; } }; smart_ptr<Resource> func(smart_ptr<Resource> temp) { // Do something return temp; } int main() { smart_ptr<Resource> res1(new Resource); // smart_ptr<Resource> res3 = res1; // Won't compile, as copy contructor is deleted smart_ptr<Resource> res3 = func(std::move(res1)); // calls move semantics return 0; }
  • This is not the exact implementation of std::unique_ptr as there is deleter, implicit cast to bool & other security features included in an actual implementation, but this gives you a bigger picture of how std::unique_ptr is implemented.

References #

  • https://www.learncpp.com/cpp-tutorial/15-1-intro-to-smart-pointers-move-semantics/
  • https://stackoverflow.com/questions/106508/what-is-a-smart-pointer-and-when-should-i-use-one
  • https://docs.microsoft.com/en-us/cpp/cpp/smart-pointers-modern-cpp?view=vs-2017

Stack Exchange Network

Stack Exchange network consists of 183 Q&A communities including Stack Overflow , the largest, most trusted online community for developers to learn, share their knowledge, and build their careers.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

My implementation for std::unique_ptr

I just finished learning about move semantics and realized that a nice practical example for this concept is unique_ptr (it cannot be copied, only moved).

For learning purposes, and as a personal experiment, I proceed to try to create my implementation for a smart unique pointer:

For a small set of test cases, this is working like the real unique_ptr .

However, it just seems too simple enough.

I have two questions regarding this code:

  • Is it well-formed? i.e. does it follow common C++ standard and patterns (for example, should private members be declared before public ones?
  • Am I missing something regarding functionality? Is there maybe a bug in my code that I'm not seeing?
  • reinventing-the-wheel

Matias Cicero's user avatar

  • \$\begingroup\$ If there is something I can do to improve my question, feel free to comment any tips, don't just leave your downvote \$\endgroup\$ –  Matias Cicero Commented May 21, 2017 at 1:30
  • \$\begingroup\$ I left a downvote and an edit. Wasn't that enough information? \$\endgroup\$ –  πάντα ῥεῖ Commented May 21, 2017 at 1:50
  • 2 \$\begingroup\$ @πάνταῥεῖ You just added a missing tag. Do I deserve a downvote for that? \$\endgroup\$ –  Matias Cicero Commented May 21, 2017 at 2:18
  • \$\begingroup\$ Do you really need to reinvent the square wheel? Can you elaborate bout why actually? \$\endgroup\$ –  πάντα ῥεῖ Commented May 21, 2017 at 3:04
  • 1 \$\begingroup\$ Did you mean to omit the members that allow you to actually use a unique pointer? I mean, operator*() and operator->() . \$\endgroup\$ –  Toby Speight Commented May 22, 2017 at 11:06

2 Answers 2

Is it well-formed?

It compiles, so yes.

i.e. does it follow common C++ standard and patterns (for example, should private members be declared before public ones?

Personally I think so.

When reading the code I want to know the members so I can verify that the constructors initialize them all, as a result I usually put them first. But other people prefer to put all private stuff at the bottom.

Am I missing something regarding functionality?

Yes. Quite a lot.

Is there maybe a bug in my code that I'm not seeing?

Yes. It potentially leaks on assignment.

Code Review

Constructing from object.

That's exceedingly dangerous:

Use member initializing list.

You should always attempt to use the member initializer list for initializing members. Any non-trivial object will have its constructor called before the initializer code is called and thus it is inefficient to then re-initialize it in the code.

Member variable Names

Prefer not to use _ as the first character in an identifier name.

Even if you know all the rules of when to use them most people don't so they are best avoided. If you must have a prefix to identify members use m_ - but if you name your member variables well then there is no need for any prefix (in my opinion prefixes makes the code worse not better, because you are relying on unwritten rules. If you have good well-defined names (see self-documenting code) then members should be obvious).

The move operators should be marked as noexcept .

When used with standard containers this will enable certain optimizations. This is because if the move is noexcept then certain operations can be guaranteed to work and thus provide the strong exception guarantee.

Leak in assignment

Note: Your current assignment potentially leaks. If this currently has a pointer assigned then you overwrite it without freeing.

Checking for this pessimization

Yes you do need to make it work when there is self assignment. But in real code the self assignment happens so infrequently that this test becomes a pessimization on the normal case (same applies for copy operation). There have been studies on this (please somebody post a link; I have lost mine and would like to add it back to my notes).

The standard way of implementing move is via swap. Just like Copy is normally implemented by Copy and Swap.

Using the swap technique also delays the calling of the destructor on the pointer for the current object. Which means that it can potentially be re-used. But if it is going out of scope the unique_ptr destructor will correctly destroy it.

Good first try but still lots of issues.

Please read the article I wrote on unique_ptr and shared_ptr for lots more things you should implement.

Smart-Pointer - Unique Pointer Smart-Pointer - Shared Pointer Smart-Pointer - Constructors

Some things you missed:

  • Constructor with nullptr
  • Constructor from derived type
  • Casting to bool
  • Checking for empty
  • Guaranteeing delete on construction failure.
  • Implicit construction issues
  • Dereferencing

When you have read all three articles then the bare bones unique_ptr looks like this:

Test to make sure it compiles:

Loki Astari's user avatar

  • \$\begingroup\$ What would be a safer way of constructing the unique_ptr from a pointer of type T? \$\endgroup\$ –  dav Commented Jul 20, 2018 at 23:18
  • \$\begingroup\$ @DavidTran. Please look at the standard version and its interface. \$\endgroup\$ –  Loki Astari Commented Jul 22, 2018 at 6:13
  • \$\begingroup\$ @Mashpoe there is no need to check if a pointer is null before calling delete. \$\endgroup\$ –  Loki Astari Commented Jan 14, 2019 at 17:02
  • \$\begingroup\$ @U62 Compiles fine for me. In both cases they are converted to the correct type before the swap. It will only fail to compile if the class U is not derived from the class T which is exactly what it is supposed to do . \$\endgroup\$ –  Loki Astari Commented Apr 5, 2019 at 16:51
  • 1 \$\begingroup\$ @user4893106 much of that constructor ridiculousness... : For an average class zero. In most situations the default implementation works out of the box with no need to do anything. For complex classes like this case there is usually a standard implementation already available in std:: . Not sure what "simple ops only" means. \$\endgroup\$ –  Loki Astari Commented Sep 3, 2020 at 18:06

Yes, have good formatting

I have the same thought present in Martin York' answer:

Yes, you forgot to add T, and T[], and the following features:

type* release();

void reset(type* item);

void swap(unique_ptr &other);

type* get();

operator->;

operator[];

Yes, you must force the receiving of types strictly to be pointers

Copy assignment operator

This is redundant, this part is not necessary as this operator will never be called taking into account that the motion constructor exists and the copy constructor is disabled (= delete).

Template only typename T

You must accept both types T, and T[], ie: array or not.

Constructing from object

Verify in move assignment operator.

Before _ptr =, you need to check if this->ptr is initialized, if yes delete ptr before assign.

This above code is incorrect, this is pointer and uptr is reference, you need to add &other to verify successfully

Note: std::move in uptr._ptr is irrelevant.

Example code

Lucas Paixão's user avatar

  • \$\begingroup\$ I certainly didn't plagiarize the answer, I adopted the same html design pattern to create my answer, but the content is different, obviously I forgot to put the proper reference to the two contents I mentioned the previous answer, being them #NoExcept and #It follow common C++, as my way of thinking is similar. Anyway, in these specific topics I added the reference to the original answer (@Martin York), thanks for the warning. \$\endgroup\$ –  Lucas Paixão Commented Sep 22, 2021 at 19:02

Your Answer

Sign up or log in, post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ c++11 reinventing-the-wheel pointers or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites

Hot Network Questions

  • Can the speed of light inhibit the synchronisation of a power grid?
  • How to make outhouses less icky?
  • Chord definition misunderstanding
  • Can you successfully substitute pickled onions for baby onions in Coq Au Vin?
  • How does a closed-cycle rocket engine keep the chamber pressure from stalling the pump turbine?
  • Linear Regulator Pass Transistor vs Parallel Regulators
  • Is this misleading "convenience fee" legal?
  • In Moon, why does Sam ask GERTY to activate a third clone before the rescue team arrives?
  • Visualizing histogram of data on unit circle?
  • Can I repair these deck support posts, or do I need to replace them?
  • bash script quoting frustration
  • SF novel where the story, or part of it, is narrated by two linked brains taking turns
  • One IO to control two LEDs. When one is lit, the other is not
  • Can I use rear (thru) axle with crack for a few rides, before getting a new one?
  • block-structure matrix
  • Is it OK to use the same field in the database to store both a percentage rate and a fixed money fee?
  • Would weightlessness (i.e. in thrill rides, planes, skydiving, etc.) be different on a Flat Earth?
  • How can I put node of a forest correctly?
  • Is the Shroud of Turin about 2000 years old?
  • The McDonald's Option
  • Reference request: "Higher order eigentuples" as generalized eigenvectors?
  • The hat-check problem
  • Postdoc supervisor has stopped helping
  • How can I push back on my co-worker's changes that I disagree with?

c unique_ptr assignment

  • <cassert> (assert.h)
  • <cctype> (ctype.h)
  • <cerrno> (errno.h)
  • C++11 <cfenv> (fenv.h)
  • <cfloat> (float.h)
  • C++11 <cinttypes> (inttypes.h)
  • <ciso646> (iso646.h)
  • <climits> (limits.h)
  • <clocale> (locale.h)
  • <cmath> (math.h)
  • <csetjmp> (setjmp.h)
  • <csignal> (signal.h)
  • <cstdarg> (stdarg.h)
  • C++11 <cstdbool> (stdbool.h)
  • <cstddef> (stddef.h)
  • C++11 <cstdint> (stdint.h)
  • <cstdio> (stdio.h)
  • <cstdlib> (stdlib.h)
  • <cstring> (string.h)
  • C++11 <ctgmath> (tgmath.h)
  • <ctime> (time.h)
  • C++11 <cuchar> (uchar.h)
  • <cwchar> (wchar.h)
  • <cwctype> (wctype.h)

Containers:

  • C++11 <array>
  • <deque>
  • C++11 <forward_list>
  • <list>
  • <map>
  • <queue>
  • <set>
  • <stack>
  • C++11 <unordered_map>
  • C++11 <unordered_set>
  • <vector>

Input/Output:

  • <fstream>
  • <iomanip>
  • <ios>
  • <iosfwd>
  • <iostream>
  • <istream>
  • <ostream>
  • <sstream>
  • <streambuf>

Multi-threading:

  • C++11 <atomic>
  • C++11 <condition_variable>
  • C++11 <future>
  • C++11 <mutex>
  • C++11 <thread>
  • <algorithm>
  • <bitset>
  • C++11 <chrono>
  • C++11 <codecvt>
  • <complex>
  • <exception>
  • <functional>
  • C++11 <initializer_list>
  • <iterator>
  • <limits>
  • <locale>
  • <memory>
  • <new>
  • <numeric>
  • C++11 <random>
  • C++11 <ratio>
  • C++11 <regex>
  • <stdexcept>
  • <string>
  • C++11 <system_error>
  • C++11 <tuple>
  • C++11 <type_traits>
  • C++11 <typeindex>
  • <typeinfo>
  • <utility>
  • <valarray>
  • C++11 allocator_arg_t
  • C++11 allocator_traits
  • auto_ptr_ref
  • C++11 bad_weak_ptr
  • C++11 default_delete
  • C++11 enable_shared_from_this
  • C++11 owner_less
  • C++11 pointer_traits
  • raw_storage_iterator
  • C++11 shared_ptr
  • C++11 unique_ptr
  • C++11 uses_allocator
  • C++11 weak_ptr

enum classes

  • C++11 pointer_safety
  • C++11 addressof
  • C++11 align
  • C++11 allocate_shared
  • C++11 const_pointer_cast
  • C++11 declare_no_pointers
  • C++11 declare_reachable
  • C++11 dynamic_pointer_cast
  • C++11 get_deleter
  • C++11 get_pointer_safety
  • get_temporary_buffer
  • C++11 make_shared
  • return_temporary_buffer
  • C++11 static_pointer_cast
  • C++11 undeclare_no_pointers
  • C++11 undeclare_reachable
  • uninitialized_copy
  • C++11 uninitialized_copy_n
  • uninitialized_fill
  • uninitialized_fill_n
  • C++11 allocator_arg

std:: unique_ptr

non-specialized
array specialization
  • a stored pointer : the pointer to the object it manages. This is set on construction , can be altered by an assignment operation or by calling member reset , and can be individually accessed for reading using members get or release .
  • a stored deleter : a callable object that takes an argument of the same type as the stored pointer and is called to delete the managed object. It is set on construction , can be altered by an assignment operation , and can be individually accessed using member get_deleter .

Template parameters

Member types.

member typedefinitionnotes
first template parameter ( )The type of the managed object
second template parameter ( )The type of the .
Defaults to <T>
, if this type exists
, otherwise
The pointer type

Member functions

Non-member function overloads.

  • C++ Data Types
  • C++ Input/Output
  • C++ Pointers
  • C++ Interview Questions
  • C++ Programs
  • C++ Cheatsheet
  • C++ Projects
  • C++ Exception Handling
  • C++ Memory Management

Unique_ptr in C++

std::unique_ptr is a smart pointer introduced in C++11. It automatically manages the dynamically allocated resources on the heap. Smart pointers are just wrappers around regular old pointers that help you prevent widespread bugs. Namely, forgetting to delete a pointer and causing a memory leak or accidentally deleting a pointer twice or in the wrong way. They can be used in a similar way to standard pointers. They automate some of the manual processes that cause common bugs.

Prerequisites: Pointer in C++ , Smart Pointers in C++.

  • unique_ptr<A>: It specifies the type of the std::unique_ptr. In this case- an object of type A.
  • new A : An object of type A is dynamically allocated on the heap using the new operator.
  • ptr1 : This is the name of the std::unique_ptr variable.

What happens when unique_ptr is used?

When we write unique_ptr<A> ptr1 (new A), memory is allocated on the heap for an instance of datatype A. ptr1 is initialized and points to newly created A object. Here, ptr1 is the only owner of the newly created object A and it manages this object’s lifetime. This means that when ptr1 is reset or goes out of scope, memory is automatically deallocated and A’s object is destroyed.

When to use unique_ptr?

When ownership of resource is required. When we want single or exclusive ownership of a resource, then we should go for unique pointers. Only one unique pointer can point to one resource. So, one unique pointer cannot be copied to another. Also, it facilitates automatic cleanup when dynamically allocated objects go out of scope and helps preventing memory leaks.

Note: We need to use the <memory> header file for using these smart pointers.

Examples of Unique_ptr

Lets create a structure A and it will have a method named printA to display some text. Then in the main section, let’s create a unique pointer that will point to the structure A. So at this point, we have an instance of structure A and p1 holds the pointer to that.

     

Now let’s create another pointer p2 and we will try to copy the pointer p1 using the assignment operator(=).

     

The above code will give compile time error as we cannot assign pointer p2 to p1 in case of unique pointers. We have to use the move semantics for such purpose as shown below.

Managing object of type A using move semantics.

       

Note once the address in pointer p1 is copied to pointer p2, the pointer p1’s address becomes NULL(0) and the address stored by p2 is now the same as the address stored by p1 showing that the address in p1 has been transferred to the pointer p2 using the move semantics.

Please Login to comment...

Similar reads.

  • Geeks Premier League
  • Geeks Premier League 2023

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Advertising & Talent Reach devs & technologists worldwide about your product, service or employer brand
  • OverflowAI GenAI features for Teams
  • OverflowAPI Train & fine-tune LLMs
  • Labs The future of collective knowledge sharing
  • About the company Visit the blog

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

c++ move/copy/assignment with a unique_ptr<AbstractClass> member variable

I have a problem very similar to

How to make a class with a member of unique_ptr work with std::move and std::swap?

and I am using VS2013 so I expect the following to work.

path\engine.cpp(75): error C2280: 'std::unique_ptr> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function with [ _Ty=AbstractCamera ] other_path\memory(1487) : see declaration of 'std::unique_ptr>::operator =' with [ _Ty=AbstractCamera ] This diagnostic occurred in the compiler generated function 'RenderManager &RenderManager::operator =(const RenderManager &)'

I do get that simple examples like

are not allowed but my problem is the following code:

because the assignment operator of unique_ptr is deleted but how does this affect a class hierarchy like those of Engine->RenderManger->unique_ptr member.

I do get, that Engine e uses the default constructor Engine() and e = Engine() calls the default constructor and the operator= of Engine to assign the temporary Engine object to e.

My question therefore is: where does the code try to copy/assign unique_ptr and how do I resolve it?

I tried to strip the original code down as much as possible but was not able to reproduce the error using a simpler example and ideone in form of a SSCCEE as I do not really understand what causes the problem, so sorry for that!

Community's user avatar

  • Yes. Sorry, this is one of the typos from the minimization of the original code as pointed out by T.C. Thank you for pointing this typo out, so I could correct it, s.t. the original question contains one error less! –  Kevin Streicher Commented Feb 20, 2015 at 19:31

3 Answers 3

VS2013 does not automatically generate move special member functions (this is non-conforming, in case it isn't obvious). You'll have to write the move constructor and move assignment operator of Engine and RenderManager yourself, as otherwise the copy special member functions will be used.

As a side note, _currentCamera(std::move(std::make_unique<CameraImpl>)) won't compile; _currentCamera(std::move(std::make_unique<CameraImpl>())) would but the std::move is useless and a pessimization. make_unique already returns an rvalue. There are also several other typos in your code, presumably caused by the minimization process.

T.C.'s user avatar

  • Thank you very much and yes, sadly you are right there are typos because of the minimization. I will try to correct them in the original post for people who read this later. I will try this now! Thank you for the fast response! Could explain what you mean with: and a pessimization , simply "uncessary"? –  Kevin Streicher Commented Feb 20, 2015 at 19:28
  • 1 @NoxMortem It inhibits copy elision. –  T.C. Commented Feb 20, 2015 at 19:41
  • oh, ouch. Thank you very much for pointing that out, this is some small but important information. –  Kevin Streicher Commented Feb 20, 2015 at 19:53

T.C. correctly answered the question, but I wanted to give some further insights as I did actually asked the wrong question :)

The real question therefore should have been

How can I use the following code
when my intent is the destruction of the default constructed object e and the assignment of the newly constructed object.

First of all one needs to understand the difference between copy and move assignment and construction and the following thread and especially the two long posts by @FredOverflow here can help very much to understand this: What are move semantics?

The problem setting are actually classes with std::vectors<std::unique_ptr<T>> and classes with std::unique_ptr<T> members. See http://www.cplusplus.com/forum/beginner/110610/ and the answer of JLJorges for a longer example.

JLJorges posted:

So don't do anything: by default B is not Copyable or Assignable, but B is Moveable and MoveAssignable

JLJorges pointed out two important things under such circumstances:

  • A class containing a non-copyable member can not be copyable by default.
  • A class containing a non-copyable but moveable/moveAssignable member can still be moveable/moveAssigneable by default.

VS2013 therefore is able to implicitly generate move and move assign operators/constructors as it does exactly this for such a class setup.

The reason I did not select T.C.'s answer altough he was very helpful and close to the answer is the following:

In case one needs copy-able/copy-assignable classes he has to implement copy-constructor and copy-assignment . This would have been the answer if I would have needed exactly what the code in the initial question looked like: a copy/copy-assignable class Engine.

In case one implements one of those methods/operators he might want to implement the others as well, see the following links for explanations:

  • Rule-of-Three becomes Rule-of-Five with C++11?
  • http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29#Rule_of_5

As I said, I had the asked the wrong question, as I did not needed a copyable/copyassignable class the solution would have been to implement move constructor and move assign operator or like JLJorges pointed out: do nothing and use the implicitly generated version, but when I wanted to move I obviously had to tell the compiler this:

e = Engine() calls Engine's move assignment operator. Since you don't have one, it's copy assignment operator will be called. Then RenderManger's copy assignment will be called. Finally it's the copy assignment of unique_ptr, which is deleted.

A move assignment is needed for Engine, as

Engine & operator = (Engine && rhs) { r._currentCamera = std::move(rhs.r._currentCamera); return * this; }

Suppose RenderManager::_currentCamera is visible to Engine, otherwise you need to defind move assignment for RenderManager.

imlyc's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged c++ c++11 or ask your own question .

  • The Overflow Blog
  • Ryan Dahl explains why Deno had to evolve with version 2.0
  • Featured on Meta
  • We've made changes to our Terms of Service & Privacy Policy - July 2024
  • Bringing clarity to status tag usage on meta sites
  • Feedback requested: How do you use tag hover descriptions for curating and do...
  • What does a new user need in a homepage experience on Stack Overflow?

Hot Network Questions

  • Fast circular buffer
  • Why don't we observe protons deflecting in J.J. Thomson's experiment?
  • In the US, can I buy iPhone and Android phones and claim them as expense?
  • A world without entropy
  • How should I respond to a former student from my old institution asking for a reference?
  • How to add a segment to an Excel radar plot
  • Are finitely discriminable groups the compact elements of the poset of marked groups?
  • Who gave God the name 'Jealous' as referred to in Exodus 34:14?
  • What is the difference between an `.iso` OS for a network and an `.iso` OS for CD?
  • Uniqueness of units in group objects
  • 32 MHz xtal on ST MB1874_HP reference schematic questions
  • Everyone hates this Key Account Manager, but company won’t act
  • I can't select a certain record with like %value%
  • Is the Shroud of Turin about 2000 years old?
  • How can I push back on my co-worker's changes that I disagree with?
  • Adverb of Place vs. Predicate nominative
  • Does my AC vent air from the room to outside?
  • How is Nationality Principle applied in practice?
  • Sun rise on Venus from East or West (North as North Eclliptic Pole)
  • Which BASIC dialect first featured a single-character comment introducer?
  • Is there a way to swap my longbow from being a ranger for a shortbow?
  • Home water pressure higher than city water pressure?
  • Calculate the sum of numbers in a rectangle
  • How to remove a file which name seems to be "." on an SMB share?

c unique_ptr assignment

COMMENTS

  1. std::unique_ptr

    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.; the managing unique_ptr object is assigned another pointer via operator= or reset().

  2. c++

    Given the common situation where the lifespan of an owned object is linked to its owner, I can use a unique pointer one of 2 ways . . It can be assigned: std::unique_ptr<someObject> owned; owner() owned=std::unique_ptr<someObject>(new someObject()); The reset method can be utilised:

  3. unique_ptr

    a stored deleter: a callable object that takes an argument of the same type as the stored pointer and is called to delete the managed object. It is set on construction, can be altered by an assignment operation, and can be individually accessed using member get_deleter. unique_ptr objects replicate a limited pointer functionality by providing ...

  4. How to: Create and use unique_ptr instances

    In this article. 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. This means that the ownership of the memory resource is transferred to another unique_ptr and the original unique_ptr no longer owns it.

  5. unique_ptr

    Constructs a unique_ptr object, depending on the signature used: default constructor (1), and (2) The object is empty (owns nothing), with value-initialized stored pointer and stored deleter. construct from pointer (3) The object takes ownership of p, initializing its stored pointer to p and value-initializing its stored deleter. construct from pointer + lvalue deleter (4)

  6. std::unique_ptr<T,Deleter>::operator=

    For the array specialization (unique_ptr<T[]>), this overload participates in overload resolution only if U is an array type, ... As a move-only type, unique_ptr's assignment operator only accepts rvalues arguments (e.g. the result of std::make_unique or a std::move 'd unique_ptr variable).

  7. std::unique_ptr<T,Deleter>::unique_ptr

    2) Constructs a std::unique_ptr which owns p, initializing the stored pointer with p and value-initializing the stored deleter. Requires that Deleter is DefaultConstructible and that construction does not throw an exception. This overload participates in overload resolution only if std:: is_default_constructible < Deleter >:: value is true and Deleter is not a pointer type.

  8. std::unique_ptr<T,Deleter>::operator=

    This assignment operator in the specialization for arrays, std::unique_ptr<T[]> behaves the same as in the primary template, except that will only participate in overload resolution if all of the following is true: U is an array type. pointer is the same type as element_type*. unique_ptr<U,E>::pointer is the same type as unique_ptr<U,E ...

  9. 22.5

    std::unique_ptr is by far the most used smart pointer class, so we'll cover that one first. In the following lessons, we'll cover std::shared_ptr and std::weak_ptr. std::unique_ptr. std::unique_ptr is the C++11 replacement for std::auto_ptr. It should be used to manage any dynamically allocated object that is not shared by multiple objects.

  10. unique_ptr

    The assignment operation between unique_ptr objects that point to different types (3) needs to be between types whose pointers are implicitly convertible, and shall not involve arrays in any case (the third signature is not part of the array specialization of unique_ptr). Copy assignment (4) to a unique_ptr type is not allowed (deleted signature).

  11. unique_ptr Class

    unique_ptr uniquely manages a resource. Each unique_ptr object stores a pointer to the object that it owns or stores a null pointer. A resource can be owned by no more than one unique_ptr object; when a unique_ptr object that owns a particular resource is destroyed, the resource is freed. A unique_ptr object may be moved, but not copied; for ...

  12. How do I pass a unique_ptr argument to a constructor or a function?

    The proper way to do this is with the std::move standard library function. If you take a unique_ptr by value, you can move from it freely. But movement doesn't actually happen because of std::move. Take the following statement: std::unique_ptr<Base> newPtr(std::move(oldPtr)); This is really two statements:

  13. Understanding unique_ptr with Example in C++11

    std::auto_ptr, and why to avoid it#. What we have seen above as smart_ptr is basically an std::auto_ptr which was introduced in C++98, was C++'s first attempt at a standardized smart pointer.; However, std::auto_ptr (and our smart_ptr class) has a number of problems that make using it dangerous. Because std::auto_ptr implements move semantics through the copy constructor and assignment ...

  14. std::unique_ptr<T,Deleter>::reset

    Return value (none) [] NoteTo replace the managed object while supplying a new deleter as well, move assignment operator may be used. A test for self-reset, i.e. whether ptr points to an object already managed by * this, is not performed, except where provided as a compiler extension or as a debugging assert.Note that code such as p. reset (p. release ()) does not involve self-reset, only code ...

  15. My implementation for std::unique_ptr

    Copy assignment operator unique_ptr<T>& operator=(const unique_ptr<T>& uptr) = delete; This is redundant, this part is not necessary as this operator will never be called taking into account that the motion constructor exists and the copy constructor is disabled (= delete).

  16. unique_ptr

    a stored deleter: a callable object that takes an argument of the same type as the stored pointer and is called to delete the managed object. It is set on construction, can be altered by an assignment operation, and can be individually accessed using member get_deleter. unique_ptr objects replicate a limited pointer functionality by providing ...

  17. c++

    Then, the operator= is only defined for rvalue references of unique pointers and not raw pointers, and a raw pointer cannot be implicitly converted to a smart pointer, to avoid accidental assignment that breaks uniqueness. Therefore a raw pointer cannot be directly assigned to it. The correct approach is put it to the constructor: std::unique_ptr<int[]> ptr (new int[3]); // ^^^^^

  18. std::unique_ptr<T,Deleter>::operator*, std::unique_ptr<T,Deleter

    pointer operator->()constnoexcept; (2) (since C++11)(constexpr since C++23) operator* and operator-> provide access to the object owned by *this . The behavior is undefined if get()== nullptr . These member functions are only provided for unique_ptr for the single objects i.e. the primary template.

  19. Unique_ptr in C++

    std::unique_ptr is a smart pointer introduced in C++11. It automatically manages the dynamically allocated resources on the heap. Smart pointers are just wrappers around regular old pointers that help you prevent widespread bugs. Namely, forgetting to delete a pointer and causing a memory leak or accidentally deleting a pointer twice or in the ...

  20. How to return a unique_ptr reference to a const type

    Please also note that if you did succeed in having unique_ptr<const Foo>& getFoo(), the caller could do mfoo.getFoo().reset(new Foo(42)), replacing the whole Foo object our from under the ManageFoo. Pointer-to-const is not the same as a const pointer, and that remains true for smart pointers. -

  21. unique_ptr assignment operator overload resolution

    unique_ptr should be used with std::move semantics, and the copy assignment operator was explicitly removed for lvalues, so that anything like. unique_ptr<int> r = another_unique_ptr; will not work. I found the following signatures on cpp reference: unique_ptr& operator=( unique_ptr&& r ); (1) template< class U, class E >.

  22. c++11

    e = Engine() calls Engine's move assignment operator. Since you don't have one, it's copy assignment operator will be called. Then RenderManger's copy assignment will be called. Finally it's the copy assignment of unique_ptr, which is deleted. A move assignment is needed for Engine, as. Engine & operator = (Engine && rhs) {.