insert_vs_emplace_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Howard Hinnant 2014.
  4. // (C) Copyright Ion Gaztanaga 2014-2014. Distributed under the Boost
  5. // Software License, Version 1.0. (See accompanying file
  6. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. // See http://www.boost.org/libs/container for documentation.
  9. //
  10. //////////////////////////////////////////////////////////////////////////////
  11. //
  12. // This testcase is based on H. Hinnant's article "Insert vs. Emplace",
  13. // (http://github.com/HowardHinnant/papers/blob/master/insert_vs_emplace.html)
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include <iostream>
  17. #include <boost/move/utility_core.hpp>
  18. #include <boost/container/vector.hpp>
  19. #include <boost/core/lightweight_test.hpp>
  20. class X
  21. {
  22. int i_;
  23. int* p_;
  24. BOOST_COPYABLE_AND_MOVABLE(X)
  25. public:
  26. struct special
  27. {
  28. unsigned c;
  29. unsigned dt;
  30. unsigned cc;
  31. unsigned ca;
  32. unsigned mc;
  33. unsigned ma;
  34. friend bool operator==(const special &l, const special &r)
  35. { return l.c == r.c && l.dt == r.dt && l.cc == r.cc && l.ca == r.ca && l.mc == r.mc && l.ma == r.ma; }
  36. };
  37. static special sp;
  38. X(int i, int* p)
  39. : i_(i)
  40. , p_(p)
  41. {
  42. // std::cout << "X(int i, int* p)\n";
  43. sp.c++;
  44. }
  45. ~X()
  46. {
  47. // std::cout << "~X()\n";
  48. sp.dt++;
  49. }
  50. X(const X& x)
  51. : i_(x.i_)
  52. , p_(x.p_)
  53. {
  54. // std::cout << "X(const X& x)\n";
  55. sp.cc++;
  56. }
  57. X& operator=(BOOST_COPY_ASSIGN_REF(X) x)
  58. {
  59. i_ = x.i_;
  60. p_ = x.p_;
  61. // std::cout << "X& operator=(const X& x)\n";
  62. sp.ca++;
  63. return *this;
  64. }
  65. X(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
  66. : i_(x.i_)
  67. , p_(x.p_)
  68. {
  69. // std::cout << "X(X&& x)\n";
  70. sp.mc++;
  71. }
  72. X& operator=(BOOST_RV_REF(X) x) BOOST_NOEXCEPT_OR_NOTHROW
  73. {
  74. i_ = x.i_;
  75. p_ = x.p_;
  76. // std::cout << "X& operator=(X&& x)\n";
  77. sp.ma++;
  78. return *this;
  79. }
  80. };
  81. std::ostream&
  82. operator<<(std::ostream& os, X::special const& sp)
  83. {
  84. os << "Const: " << sp.c << '\n';
  85. os << "Destr: " << sp.dt << '\n';
  86. os << "CopyC: " << sp.cc << '\n';
  87. os << "CopyA: " << sp.ca << '\n';
  88. os << "MoveC: " << sp.mc << '\n';
  89. os << "MoveA: " << sp.ma << '\n';
  90. os << "Total: " << (sp.c + sp.dt + sp.cc + sp.ca + sp.mc + sp.ma) << '\n';
  91. return os;
  92. }
  93. X::special X::sp = X::special();
  94. const X produce_const_prvalue()
  95. { return X(0, 0); }
  96. int main()
  97. {
  98. X::special insert_results;
  99. X::special emplace_results;
  100. {
  101. boost::container::vector<X> v;
  102. v.reserve(4);
  103. v.push_back(X(0,0));
  104. v.push_back(X(0,0));
  105. v.push_back(X(0,0));
  106. X x(0,0);
  107. std::cout << "--insert lvalue no reallocation--\n";
  108. X::sp = X::special();
  109. v.insert(v.begin(), x);
  110. std::cout << X::sp;
  111. std::cout << "----\n";
  112. insert_results = X::sp;
  113. }
  114. {
  115. boost::container::vector<X> v;
  116. v.reserve(4);
  117. v.push_back(X(0,0));
  118. v.push_back(X(0,0));
  119. v.push_back(X(0,0));
  120. X x(0,0);
  121. std::cout << "--emplace lvalue no reallocation--\n";
  122. X::sp = X::special();
  123. v.emplace(v.begin(), x);
  124. std::cout << X::sp;
  125. std::cout << "----\n";
  126. emplace_results = X::sp;
  127. }
  128. {
  129. boost::container::vector<X> v;
  130. v.reserve(4);
  131. v.push_back(X(0,0));
  132. v.push_back(X(0,0));
  133. v.push_back(X(0,0));
  134. X x(0,0);
  135. std::cout << "--insert xvalue no reallocation--\n";
  136. X::sp = X::special();
  137. v.insert(v.begin(), boost::move(x));
  138. std::cout << X::sp;
  139. std::cout << "----\n";
  140. insert_results = X::sp;
  141. }
  142. {
  143. boost::container::vector<X> v;
  144. v.reserve(4);
  145. v.push_back(X(0,0));
  146. v.push_back(X(0,0));
  147. v.push_back(X(0,0));
  148. X x(0,0);
  149. std::cout << "--emplace xvalue no reallocation--\n";
  150. X::sp = X::special();
  151. v.emplace(v.begin(), boost::move(x));
  152. std::cout << X::sp;
  153. std::cout << "----\n";
  154. emplace_results = X::sp;
  155. }
  156. BOOST_TEST_EQ(insert_results == emplace_results, true);
  157. {
  158. boost::container::vector<X> v;
  159. v.reserve(4);
  160. v.push_back(X(0,0));
  161. v.push_back(X(0,0));
  162. v.push_back(X(0,0));
  163. X x(0,0);
  164. std::cout << "--emplace const prvalue no reallocation--\n";
  165. X::sp = X::special();
  166. v.emplace(v.begin(), produce_const_prvalue());
  167. std::cout << X::sp;
  168. std::cout << "----\n";
  169. emplace_results = X::sp;
  170. }
  171. {
  172. boost::container::vector<X> v;
  173. v.reserve(4);
  174. v.push_back(X(0,0));
  175. v.push_back(X(0,0));
  176. v.push_back(X(0,0));
  177. X x(0,0);
  178. std::cout << "--emplace const prvalue no reallocation--\n";
  179. X::sp = X::special();
  180. v.insert(v.begin(), produce_const_prvalue());
  181. std::cout << X::sp;
  182. std::cout << "----\n";
  183. insert_results = X::sp;
  184. }
  185. BOOST_TEST_EQ(insert_results == emplace_results, true);
  186. {
  187. boost::container::vector<X> v;
  188. v.reserve(4);
  189. v.push_back(X(0,0));
  190. v.push_back(X(0,0));
  191. v.push_back(X(0,0));
  192. std::cout << "--insert rvalue no reallocation--\n";
  193. X::sp = X::special();
  194. v.insert(v.begin(), X(0,0));
  195. std::cout << X::sp;
  196. std::cout << "----\n";
  197. insert_results = X::sp;
  198. }
  199. {
  200. boost::container::vector<X> v;
  201. v.reserve(4);
  202. v.push_back(X(0,0));
  203. v.push_back(X(0,0));
  204. v.push_back(X(0,0));
  205. std::cout << "--emplace rvalue no reallocation--\n";
  206. X::sp = X::special();
  207. v.emplace(v.begin(), X(0,0));
  208. std::cout << X::sp;
  209. std::cout << "----\n";
  210. emplace_results = X::sp;
  211. }
  212. //With emulated move semantics an extra copy is unavoidable
  213. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  214. BOOST_TEST_EQ(insert_results == emplace_results, true);
  215. #endif
  216. {
  217. boost::container::vector<X> v;
  218. v.reserve(3);
  219. v.push_back(X(0,0));
  220. v.push_back(X(0,0));
  221. v.push_back(X(0,0));
  222. X x(0,0);
  223. std::cout << "--insert lvalue reallocation--\n";
  224. X::sp = X::special();
  225. v.insert(v.begin(), x);
  226. std::cout << X::sp;
  227. std::cout << "----\n";
  228. insert_results = X::sp;
  229. }
  230. {
  231. boost::container::vector<X> v;
  232. v.reserve(3);
  233. v.push_back(X(0,0));
  234. v.push_back(X(0,0));
  235. v.push_back(X(0,0));
  236. X x(0,0);
  237. std::cout << "--emplace lvalue reallocation--\n";
  238. X::sp = X::special();
  239. v.emplace(v.begin(), x);
  240. std::cout << X::sp;
  241. std::cout << "----\n";
  242. emplace_results = X::sp;
  243. }
  244. BOOST_TEST_EQ(insert_results == emplace_results, true);
  245. {
  246. boost::container::vector<X> v;
  247. v.reserve(3);
  248. v.push_back(X(0,0));
  249. v.push_back(X(0,0));
  250. v.push_back(X(0,0));
  251. X x(0,0);
  252. std::cout << "--insert xvalue reallocation--\n";
  253. X::sp = X::special();
  254. v.insert(v.begin(), boost::move(x));
  255. std::cout << X::sp;
  256. std::cout << "----\n";
  257. insert_results = X::sp;
  258. }
  259. {
  260. boost::container::vector<X> v;
  261. v.reserve(3);
  262. v.push_back(X(0,0));
  263. v.push_back(X(0,0));
  264. v.push_back(X(0,0));
  265. X x(0,0);
  266. std::cout << "--emplace xvalue reallocation--\n";
  267. X::sp = X::special();
  268. v.emplace(v.begin(), boost::move(x));
  269. std::cout << X::sp;
  270. std::cout << "----\n";
  271. emplace_results = X::sp;
  272. }
  273. BOOST_TEST_EQ(insert_results == emplace_results, true);
  274. {
  275. boost::container::vector<X> v;
  276. v.reserve(3);
  277. v.push_back(X(0,0));
  278. v.push_back(X(0,0));
  279. v.push_back(X(0,0));
  280. std::cout << "--insert rvalue reallocation--\n";
  281. X::sp = X::special();
  282. v.insert(v.begin(), X(0,0));
  283. std::cout << X::sp;
  284. std::cout << "----\n";
  285. insert_results = X::sp;
  286. }
  287. {
  288. boost::container::vector<X> v;
  289. v.reserve(3);
  290. v.push_back(X(0,0));
  291. v.push_back(X(0,0));
  292. v.push_back(X(0,0));
  293. std::cout << "--emplace rvalue reallocation--\n";
  294. X::sp = X::special();
  295. v.emplace(v.begin(), X(0,0));
  296. std::cout << X::sp;
  297. std::cout << "----\n";
  298. emplace_results = X::sp;
  299. }
  300. //With emulated move semantics an extra copy is unavoidable
  301. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  302. BOOST_TEST_EQ(insert_results == emplace_results, true);
  303. #endif
  304. {
  305. boost::container::vector<X> v;
  306. v.reserve(4);
  307. v.push_back(X(0,0));
  308. v.push_back(X(0,0));
  309. v.push_back(X(0,0));
  310. X x(0,0);
  311. std::cout << "--push_back lvalue no reallocation--\n";
  312. X::sp = X::special();
  313. v.push_back(x);
  314. std::cout << X::sp;
  315. std::cout << "----\n";
  316. insert_results = X::sp;
  317. }
  318. {
  319. boost::container::vector<X> v;
  320. v.reserve(4);
  321. v.push_back(X(0,0));
  322. v.push_back(X(0,0));
  323. v.push_back(X(0,0));
  324. X x(0,0);
  325. std::cout << "--emplace_back lvalue no reallocation--\n";
  326. X::sp = X::special();
  327. v.emplace_back(x);
  328. std::cout << X::sp;
  329. std::cout << "----\n";
  330. emplace_results = X::sp;
  331. }
  332. BOOST_TEST_EQ(insert_results == emplace_results, true);
  333. {
  334. boost::container::vector<X> v;
  335. v.reserve(4);
  336. v.push_back(X(0,0));
  337. v.push_back(X(0,0));
  338. v.push_back(X(0,0));
  339. X x(0,0);
  340. std::cout << "--push_back xvalue no reallocation--\n";
  341. X::sp = X::special();
  342. v.push_back(boost::move(x));
  343. std::cout << X::sp;
  344. std::cout << "----\n";
  345. insert_results = X::sp;
  346. }
  347. {
  348. boost::container::vector<X> v;
  349. v.reserve(4);
  350. v.push_back(X(0,0));
  351. v.push_back(X(0,0));
  352. v.push_back(X(0,0));
  353. X x(0,0);
  354. std::cout << "--emplace_back xvalue no reallocation--\n";
  355. X::sp = X::special();
  356. v.emplace_back(boost::move(x));
  357. std::cout << X::sp;
  358. std::cout << "----\n";
  359. emplace_results = X::sp;
  360. }
  361. BOOST_TEST_EQ(insert_results == emplace_results, true);
  362. {
  363. boost::container::vector<X> v;
  364. v.reserve(4);
  365. v.push_back(X(0,0));
  366. v.push_back(X(0,0));
  367. v.push_back(X(0,0));
  368. std::cout << "--push_back rvalue no reallocation--\n";
  369. X::sp = X::special();
  370. v.push_back(X(0,0));
  371. std::cout << X::sp;
  372. std::cout << "----\n";
  373. insert_results = X::sp;
  374. }
  375. {
  376. boost::container::vector<X> v;
  377. v.reserve(4);
  378. v.push_back(X(0,0));
  379. v.push_back(X(0,0));
  380. v.push_back(X(0,0));
  381. std::cout << "--emplace_back rvalue no reallocation--\n";
  382. X::sp = X::special();
  383. v.emplace_back(X(0,0));
  384. std::cout << X::sp;
  385. std::cout << "----\n";
  386. emplace_results = X::sp;
  387. }
  388. //With emulated move semantics an extra copy is unavoidable
  389. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  390. BOOST_TEST_EQ(insert_results == emplace_results, true);
  391. #endif
  392. {
  393. boost::container::vector<X> v;
  394. v.reserve(3);
  395. v.push_back(X(0,0));
  396. v.push_back(X(0,0));
  397. v.push_back(X(0,0));
  398. X x(0,0);
  399. std::cout << "--push_back lvalue reallocation--\n";
  400. X::sp = X::special();
  401. v.push_back(x);
  402. std::cout << X::sp;
  403. std::cout << "----\n";
  404. insert_results = X::sp;
  405. }
  406. {
  407. boost::container::vector<X> v;
  408. v.reserve(3);
  409. v.push_back(X(0,0));
  410. v.push_back(X(0,0));
  411. v.push_back(X(0,0));
  412. X x(0,0);
  413. std::cout << "--emplace_back lvalue reallocation--\n";
  414. X::sp = X::special();
  415. v.emplace_back(x);
  416. std::cout << X::sp;
  417. std::cout << "----\n";
  418. emplace_results = X::sp;
  419. }
  420. BOOST_TEST_EQ(insert_results == emplace_results, true);
  421. {
  422. boost::container::vector<X> v;
  423. v.reserve(3);
  424. v.push_back(X(0,0));
  425. v.push_back(X(0,0));
  426. v.push_back(X(0,0));
  427. X x(0,0);
  428. std::cout << "--push_back xvalue reallocation--\n";
  429. X::sp = X::special();
  430. v.push_back(boost::move(x));
  431. std::cout << X::sp;
  432. std::cout << "----\n";
  433. insert_results = X::sp;
  434. }
  435. {
  436. boost::container::vector<X> v;
  437. v.reserve(3);
  438. v.push_back(X(0,0));
  439. v.push_back(X(0,0));
  440. v.push_back(X(0,0));
  441. X x(0,0);
  442. std::cout << "--emplace_back xvalue reallocation--\n";
  443. X::sp = X::special();
  444. v.emplace_back(boost::move(x));
  445. std::cout << X::sp;
  446. std::cout << "----\n";
  447. emplace_results = X::sp;
  448. }
  449. BOOST_TEST_EQ(insert_results == emplace_results, true);
  450. {
  451. boost::container::vector<X> v;
  452. v.reserve(3);
  453. v.push_back(X(0,0));
  454. v.push_back(X(0,0));
  455. v.push_back(X(0,0));
  456. std::cout << "--push_back rvalue reallocation--\n";
  457. X::sp = X::special();
  458. v.push_back(X(0,0));
  459. std::cout << X::sp;
  460. std::cout << "----\n";
  461. insert_results = X::sp;
  462. }
  463. {
  464. boost::container::vector<X> v;
  465. v.reserve(3);
  466. v.push_back(X(0,0));
  467. v.push_back(X(0,0));
  468. v.push_back(X(0,0));
  469. std::cout << "--emplace_back rvalue reallocation--\n";
  470. X::sp = X::special();
  471. v.emplace_back(X(0,0));
  472. std::cout << X::sp;
  473. std::cout << "----\n";
  474. emplace_results = X::sp;
  475. }
  476. //With emulated move semantics an extra copy is unavoidable
  477. #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
  478. BOOST_TEST_EQ(insert_results == emplace_results, true);
  479. #endif
  480. return boost::report_errors();
  481. }