fork(1) download
  1. #include <iostream>
  2. #include <utility>
  3. #include <string>
  4.  
  5. class Var
  6. {
  7. private:
  8. struct controlBlockBase
  9. {
  10. unsigned short uses;
  11.  
  12. controlBlockBase() : uses(1) { }
  13. virtual ~controlBlockBase() { }
  14. };
  15.  
  16. template <class K>
  17. struct controlBlockImpl : controlBlockBase
  18. {
  19. K value;
  20. controlBlockImpl(const K &val) : controlBlockBase(), value(val) {}
  21. };
  22.  
  23. controlBlockBase *cb;
  24.  
  25. public:
  26. Var() : cb(nullptr) {
  27. std::cout << "Var default constructed" << std::endl;
  28. }
  29.  
  30. template<typename K>
  31. Var(const K &value) : cb(new controlBlockImpl<K>(value)) {
  32. std::cout << "Var value constructed" << std::endl;
  33. }
  34.  
  35. Var(const Var &obj) : cb(obj.cb) {
  36. if (cb) {
  37. ++(cb->uses);
  38. }
  39. std::cout << "Var copy constructed" << std::endl;
  40. }
  41.  
  42. Var(Var &&obj) : cb(nullptr) {
  43. obj.swap(*this);
  44. std::cout << "Var move constructed" << std::endl;
  45. }
  46.  
  47. ~Var() {
  48. if ((cb) && ((cb->uses -= 1) <= 0)) {
  49. delete cb;
  50. cb = nullptr;
  51. }
  52. std::cout << "Var destructed" << std::endl;
  53. }
  54.  
  55. Var& operator=(const Var& obj) {
  56. if (this != &obj) {
  57. Var(obj).swap(*this);
  58. }
  59. std::cout << "Var copy assigned" << std::endl;
  60. return *this;
  61. }
  62.  
  63. Var& operator=(Var &&obj) {
  64. obj.swap(*this);
  65. std::cout << "Var move assigned" << std::endl;
  66. return *this;
  67. }
  68.  
  69. void swap(Var &other) {
  70. std::swap(cb, other.cb);
  71. }
  72.  
  73. unsigned short getUses() const {
  74. return (cb) ? cb->uses : 0;
  75. }
  76. };
  77.  
  78. namespace std {
  79. void swap(Var &v1, Var &v2) {
  80. v1.swap(v2);
  81. }
  82. }
  83.  
  84. class C
  85. {
  86. public:
  87. Var var;
  88.  
  89. C() {
  90. std::cout << "C default constructed" << std::endl;
  91. }
  92.  
  93. C(const C &c) : var(c.var) {
  94. std::cout << "C copy constructed" << std::endl;
  95. }
  96.  
  97. C(C &&c) : var(std::move(c.var)) {
  98. std::cout << "C move constructed" << std::endl;
  99. }
  100.  
  101. C(Var var) : var(var) {
  102. std::cout << "C value constructed" << std::endl;
  103. }
  104.  
  105. ~C() {
  106. std::cout << "C destructed" << std::endl;
  107. }
  108.  
  109. C& operator=(const C &c) {
  110. if (this != &c) {
  111. C tmp(c);
  112. std::swap(var, tmp.var);
  113. }
  114. std::cout << "C copy assigned" << std::endl;
  115. return *this;
  116. }
  117.  
  118. C& operator=(C &&c) {
  119. std::swap(var, c.var);
  120. std::cout << "C move assigned" << std::endl;
  121. return *this;
  122. }
  123. };
  124.  
  125. class MyString
  126. {
  127. public:
  128. std::string str;
  129.  
  130. MyString() {
  131. std::cout << "MyString default constructed" << std::endl;
  132. }
  133.  
  134. MyString(const char *s) : str(s) {
  135. std::cout << "MyString value constructed" << std::endl;
  136. }
  137.  
  138. MyString(const std::string &s) : str(s) {
  139. std::cout << "MyString value constructed" << std::endl;
  140. }
  141.  
  142. MyString(const MyString &s) : str(s.str) {
  143. std::cout << "MyString copy constructed" << std::endl;
  144. }
  145.  
  146. MyString(MyString &&s) : str(std::move(s.str)) {
  147. std::cout << "MyString move constructed" << std::endl;
  148. }
  149.  
  150. ~MyString() {
  151. std::cout << "MyString destructed" << std::endl;
  152. }
  153.  
  154. MyString& operator=(const MyString &s) {
  155. if (this != &s) {
  156. str = s.str;
  157. }
  158. std::cout << "MyString copy assigned" << std::endl;
  159. return *this;
  160. }
  161.  
  162. MyString& operator=(MyString &&s) {
  163. str = std::move(s.str);
  164. std::cout << "MyString move assigned" << std::endl;
  165. return *this;
  166. }
  167. };
  168.  
  169. void test()
  170. {
  171. MyString string = "Hello";
  172. Var var1 = Var(string);
  173. std::cout << "var1 uses=" << var1.getUses() << std::endl;
  174. C c = C(var1);
  175. std::cout << "var1 uses=" << var1.getUses() << std::endl;
  176. Var var2 = Var(c);
  177. std::cout << "var1 uses=" << var1.getUses() << std::endl;
  178. std::cout << "var2 uses=" << var2.getUses() << std::endl;
  179. }
  180.  
  181. int main() {
  182. test();
  183. return 0;
  184. }
Success #stdin #stdout 0s 15248KB
stdin
Standard input is empty
stdout
MyString value constructed
MyString copy constructed
Var value constructed
var1 uses=1
Var copy constructed
Var copy constructed
C value constructed
Var destructed
var1 uses=2
Var copy constructed
C copy constructed
Var value constructed
var1 uses=3
var2 uses=1
C destructed
Var destructed
Var destructed
C destructed
Var destructed
MyString destructed
Var destructed
MyString destructed