fork download
  1. // http://stackoverflow.com/questions/19826045/trying-to-write-move-constructor-in-terms-of-move-assignment/19846215#19846215
  2. // https://i...content-available-to-author-only...e.com/AnwDvD
  3. #include<algorithm>
  4. #include<cassert>
  5. #include<cstring>
  6. #include<iostream>
  7.  
  8. class String
  9. {
  10. char* m_data;
  11. int m_len;
  12. public:
  13. const volatile String&& operator=(String&) volatile const = delete; // make it as undesirable as possible!
  14. void swap(String& rhs) throw()
  15. {
  16. std::cout << __PRETTY_FUNCTION__ << std::endl;
  17. std::swap(m_data, rhs.m_data);
  18. std::swap(m_len, rhs.m_len);
  19. }
  20. template<typename T>
  21. String& operator=(T templated_copy_and_swap) {
  22. std::cout << __PRETTY_FUNCTION__ << " (Templated ) Assignment by (optional) copy and (not-optional) swap" << std::endl;
  23. templated_copy_and_swap.swap(*this);
  24. return *this;
  25. }
  26. String(String&& move_constructor) throw() // The move constructor, we wish to use operator= here
  27. : m_data(NULL)
  28. , m_len(0)
  29. {
  30. std::cout << __PRETTY_FUNCTION__ << std::endl;
  31. //move_constructor.swap(*this); // This was the original line we wish to replace
  32. operator=(std::move(move_constructor)); // It works!
  33. }
  34. String& operator=(String && move_assignment) {
  35. std::cout << __PRETTY_FUNCTION__ << std::endl;
  36. move_assignment.swap(*this);
  37. return *this;
  38. }
  39.  
  40. /* Below are just some other constructors that are required
  41.   * to build a working demonstration
  42.   */
  43. String(const String &copy_constructor) {
  44. std::cout << __PRETTY_FUNCTION__ << " Copy constructor" << std::endl;
  45. m_len = copy_constructor.m_len;
  46. m_data = new char[m_len+1];
  47. strncpy(m_data, copy_constructor.m_data, m_len+1);
  48. }
  49. ~String() {
  50. std::cout << __PRETTY_FUNCTION__ << std::endl;
  51. if(m_data) {
  52. std::cout << " ~\"" << m_data << "\"" << std::endl;
  53. delete[] m_data;
  54. } // otherwise, this String was moved-from. Nothing to delete
  55. }
  56. template<size_t lenPlusOne>
  57. explicit String(const char (&x)[lenPlusOne]) {
  58. std::cout << __PRETTY_FUNCTION__ << std::endl;
  59. m_data = new char[lenPlusOne];
  60. strncpy(m_data, x, lenPlusOne);
  61. m_len = lenPlusOne - 1; // to deal with the trailing '\0'
  62. assert(m_data[m_len] == '\0');
  63. }
  64. };
  65.  
  66.  
  67. String returnsT() {
  68. std::cout << __PRETTY_FUNCTION__ << " Inside returnsT(). It will do some stuff here." << std::endl;
  69. String s("returnsT");
  70. std::cout << __PRETTY_FUNCTION__ << " Inside returnsT(). About to return." << std::endl;
  71. return s;
  72. }
  73.  
  74. int main() {
  75. String s1("first");
  76. String s2("second");
  77. String s3("third");
  78.  
  79. std::cout << std::endl;
  80. std::cout << " === Situation A): Assign from l-value. Copy required." << std::endl << std::endl;
  81. s1 = s2;
  82.  
  83. {
  84. std::cout << std::endl;
  85. std::cout << " === Situation B): Assign from returnsT() returning T. C++03 can optimize this, no copy *OR* move required after the return." << std::endl << std::endl;
  86. s1 = returnsT();
  87. }
  88.  
  89. {
  90. std::cout << std::endl;
  91. std::cout << " === Situation C): Assign from move() returning T&&." << std::endl << std::endl;
  92. s1 = std::move(s3) ;
  93. //s1 = StringRVRef(std::move(s3));
  94. }
  95.  
  96. std::cout << std::endl;
  97. std::cout << " === Done. main() will finish now, destructing the three local strings." << std::endl << std::endl;
  98. }
  99.  
Success #stdin #stdout 0s 3476KB
stdin
Standard input is empty
stdout
String::String(const char (&)[lenPlusOne]) [with unsigned int lenPlusOne = 6u]
String::String(const char (&)[lenPlusOne]) [with unsigned int lenPlusOne = 7u]
String::String(const char (&)[lenPlusOne]) [with unsigned int lenPlusOne = 6u]

 === Situation A): Assign from l-value. Copy required.

String::String(const String&)     Copy constructor
String& String::operator=(T) [with T = String]  (Templated  ) Assignment by (optional) copy and (not-optional) swap
void String::swap(String&)
String::~String()
 ~"first"

 === Situation B): Assign from returnsT() returning T.  C++03 can optimize this, no copy *OR* move required after the return.

String returnsT()    Inside returnsT().  It will do some stuff here.
String::String(const char (&)[lenPlusOne]) [with unsigned int lenPlusOne = 9u]
String returnsT()    Inside returnsT().  About to return.
String& String::operator=(String&&)
void String::swap(String&)
String::~String()
 ~"second"

 === Situation C): Assign from move() returning T&&.

String& String::operator=(String&&)
void String::swap(String&)

 === Done. main() will finish now, destructing the three local strings.

String::~String()
 ~"returnsT"
String::~String()
 ~"second"
String::~String()
 ~"third"