Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does std::make_shared() use custom allocators?

Consider this code:

#include <memory>
#include <iostream>


class SomeClass {
public:
    SomeClass() {
        std::cout << "SomeClass()" << std::endl;
    }

    ~SomeClass() {
        std::cout << "~SomeClass()" << std::endl;
    }

    void* operator new(std::size_t size) {
        std::cout << "Custom new" << std::endl;
        return ::operator new(size);
    }

    void operator delete(void* ptr, std::size_t size) {
        std::cout << "Custom delete" << std::endl;
        ::operator delete(ptr);
    }
};



int main() {
    std::shared_ptr<SomeClass> ptr1(new SomeClass);
    std::cout << std::endl << "Another one..." << std::endl << std::endl;
    std::shared_ptr<SomeClass> ptr2(std::make_shared<SomeClass>());
    std::cout << std::endl << "Done!" << std::endl << std::endl;
}

Here is its output:

Custom new
SomeClass()

Another one...

SomeClass()

Done!

~SomeClass()
~SomeClass()
Custom delete

Clearly, std::make_shared() didn't call the new operator -- it's using a custom allocator. Is this the standard behavior for std::make_shared()?

like image 975
Mark Garcia Avatar asked Dec 29 '12 09:12

Mark Garcia


People also ask

What is std :: Make_shared?

std::make_sharedAllocates and constructs an object of type T passing args to its constructor, and returns an object of type shared_ptr<T> that owns and stores a pointer to it (with a use count of 1). This function uses ::new to allocate storage for the object.

Does Make_shared throw?

So, if you throw exception from your class' constructor, then std::make_shared will throw it too. Besides exceptions thrown from constructor, std::make_shared could throw std::bad_alloc exception on its own.

Why is Make_shared more efficient?

One reason is because make_shared allocates the reference count together with the object to be managed in the same block of memory. OK, I got the point. This is of course more efficient than two separate allocation operations.

What is shared pointer in C++ example?

The shared_ptr type is a smart pointer in the C++ standard library that is designed for scenarios in which more than one owner might have to manage the lifetime of the object in memory.


2 Answers

Yes, this is standard behavior. From the standard (§20.7.2.2.6 shared_ptr creation ):

Effects: Allocates memory suitable for an object of type T and constructs an object in that memory via the placement new expression ::new (pv) T(std::forward<Args>(args)...).

This allows make_shared to allocate the storage for both the object and the data structure for the shared pointer itself (the "control block") in a single allocation, for efficiency reasons.

You could use std::allocate_shared if you want to control that storage allocation.

like image 112
Mat Avatar answered Sep 22 '22 06:09

Mat


To expand on Mat's correct answer, make_shared is typically implemented by allocating an object that contains the shared_ptr reference counts and a buffer of uninitialized bytes:

template<typename T>
  struct shared_count_inplace
  {
    long m_count;
    long weak_count;
    typename std::aligned_storage<sizeof(T)>::type m_storage;
    // ...
  };

This is the type which will be allocated on the heap, not your type, so your type's new is not called. Then your type will be constructed using placement new at the location (void*)&m_storage.

like image 5
Jonathan Wakely Avatar answered Sep 23 '22 06:09

Jonathan Wakely