You are expected to use std::make_shared
to ensure that block with counters is stored next to data. Unfortunately internally std::make_shared<T>
uses zero initialization for T
(i.e. uses T()
to initialize data block). Is there any way to trick it into using default initialization? I know I can use std::shared_ptr<T>( new T, [](auto p){delete p;})
, but I'll end up with two allocations here (data and counter blocks won't be next to each other).
Asked
Active
Viewed 774 times
5

Shreevardhan
- 12,233
- 3
- 36
- 50

C.M.
- 3,071
- 1
- 14
- 33
-
2default initialization of `T` is `T()`. `new T` is same to `new T()`. Also, there is no need in specifying default deleter. What exactly are you trying to achieve? – Andrei R. Feb 01 '17 at 06:17
-
2make a wrapper of T with a constructor that does default initialization – M.M Feb 01 '17 at 06:28
-
3@AndreiR. No, that is incorrect. `T()` is value initialization, and that can make a difference. – juanchopanza Feb 01 '17 at 06:44
-
4@AndreiR. : None of that is true beginning with C++03. – ildjarn Feb 01 '17 at 06:48
-
1sorry, forgot to add "for non-trivial types (structs/classes)" – Andrei R. Feb 01 '17 at 07:09
-
2@AndreiR. also applies to structs and classes (which are the same thing.) It depends mainly on whether the type has a user declared default constructor. – juanchopanza Feb 01 '17 at 07:10
-
4@Andrei R. No, "new T" is not the same as "new T()" – C.M. Feb 02 '17 at 03:22
1 Answers
9
Create a derived class to enforce trivial construction.
struct D : T {
D() {} // Non-trivial constructor. Default-initialize T, which may be trivial.
};
Construct the derived class but assign it to the shared pointer you want.
std::shared_ptr< T > p = std::make_shared< D >();
Note that this is type-safe with respect to the destructor. shared_ptr
always performs type erasure and uses dynamic dispatch before the destructor call, even for simple POD objects.

Potatoswatter
- 134,909
- 25
- 265
- 421
-
-
Yeah... Type erasure is something I don't really appreciate in std::shared_ptr. But I deal with large old codebase that has like 4 different homegrown smart pointers -- regardless how you look at it std::shared_ptr is better than any of them :-) – C.M. Feb 02 '17 at 03:25
-
Yum: `template
ListInit(Args&&...args):T{std::forward – Yakk - Adam Nevraumont Feb 02 '17 at 15:10(args)...}{}` -
@Yakk Use inheriting constructors. (Edit: Or just don't construct the derived class for cases of nontrivial construction. It's a bit of a corner case that trivial constructors are allowed to overload user-defined ones…) – Potatoswatter Feb 03 '17 at 08:54
-
even better solution -- [lambda](https://stackoverflow.com/questions/45345175/avoiding-extra-move-in-make-unique-make-shared-emplace-etc-for-structures-that-u)! – C.M. Aug 05 '17 at 09:44