1515#include < bsoncxx/v1/detail/macros.hpp>
1616
1717#include < cstring>
18+ #include < memory>
1819
1920#include < bsoncxx/builder/core.hpp>
2021#include < bsoncxx/exception/error_code.hpp>
@@ -72,14 +73,33 @@ class managed_bson_t {
7273
7374class core ::impl {
7475 public:
75- impl (bool is_array) : _depth(0 ), _root_is_array(is_array), _n(0 ), _has_user_key(false ) {}
76+ ~impl () {
77+ _root_ptr->~managed_bson_t ();
78+ }
79+
80+ impl (impl&&) = delete ;
81+ impl& operator =(impl&&) = delete ;
82+
83+ impl (impl const &) = delete ;
84+ impl& operator =(impl const &) = delete ;
85+
86+ impl (bool is_array)
87+ : _depth(0 ),
88+ _root_is_array (is_array),
89+ _n(0 ),
90+ _root_ptr([this ] {
91+ void * ptr = _root_storage;
92+ std::size_t space = sizeof (_root_storage);
93+ return new (std::align (alignof (managed_bson_t ), sizeof (managed_bson_t ), ptr, space)) managed_bson_t ();
94+ }()),
95+ _has_user_key(false ) {}
7696
7797 void reinit () {
7898 while (!_stack.empty ()) {
7999 _stack.pop_back ();
80100 }
81101
82- bson_reinit (_root. get ());
102+ bson_reinit (_root_ptr-> get ());
83103
84104 _depth = 0 ;
85105
@@ -95,8 +115,8 @@ class core::impl {
95115 }
96116
97117 uint32_t buf_len;
98- uint8_t * buf_ptr = bson_destroy_with_steal (_root. get (), true , &buf_len);
99- bson_init (_root. get ());
118+ uint8_t * buf_ptr = bson_destroy_with_steal (_root_ptr-> get (), true , &buf_len);
119+ bson_init (_root_ptr-> get ());
100120
101121 return bsoncxx::v_noabi::document::value{buf_ptr, buf_len, bson_free_deleter};
102122 }
@@ -108,15 +128,15 @@ class core::impl {
108128 }
109129
110130 uint32_t buf_len;
111- uint8_t * buf_ptr = bson_destroy_with_steal (_root. get (), true , &buf_len);
112- bson_init (_root. get ());
131+ uint8_t * buf_ptr = bson_destroy_with_steal (_root_ptr-> get (), true , &buf_len);
132+ bson_init (_root_ptr-> get ());
113133
114134 return bsoncxx::v_noabi::array::value{buf_ptr, buf_len, bson_free_deleter};
115135 }
116136
117137 bson_t * back () {
118138 if (_stack.empty ()) {
119- return _root. get ();
139+ return _root_ptr-> get ();
120140 } else {
121141 return &_stack.back ().bson ;
122142 }
@@ -178,7 +198,7 @@ class core::impl {
178198 throw bsoncxx::v_noabi::exception{error_code::k_cannot_perform_document_operation_on_array};
179199 }
180200
181- return _root. get ();
201+ return _root_ptr-> get ();
182202 }
183203
184204 // Throws bsoncxx::v_noabi::exception if the top-level BSON datum is a document.
@@ -187,7 +207,7 @@ class core::impl {
187207 throw bsoncxx::v_noabi::exception{error_code::k_cannot_perform_array_operation_on_document};
188208 }
189209
190- return _root. get ();
210+ return _root_ptr-> get ();
191211 }
192212
193213 bool is_array () {
@@ -239,7 +259,9 @@ class core::impl {
239259
240260 bool _root_is_array;
241261 std::size_t _n;
242- managed_bson_t _root;
262+
263+ unsigned char _root_storage[2u * sizeof (managed_bson_t )];
264+ managed_bson_t * _root_ptr;
243265
244266 // The bottom frame of _stack has _root as its parent.
245267 stack<frame, 4 > _stack;
0 commit comments