Skip to content

Instantly share code, notes, and snippets.

@aqjune
Created November 20, 2018 09:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aqjune/42dadb00e8960042c842404ca266d70d to your computer and use it in GitHub Desktop.
Save aqjune/42dadb00e8960042c842404ca266d70d to your computer and use it in GitHub Desktop.
C++'s move semantics - example
#include <vector>
#include <iostream>
#include<utility>
using namespace std;
class C {
public:
int *ptr;
C(int val) {
cout << " Constructor: " << (intptr_t) this << endl;
ptr = new int;
*ptr = val;
}
~C() {
cout << " Destructor: " << (intptr_t)this << endl;
delete ptr;
ptr = (int *)191919231;
}
C(C &c) {
c... = asdf;
}
C(const C &c) {
cout << " Copy constructor: " << (intptr_t)this << endl;
this->ptr = new int;
*this->ptr = *c.ptr;
}
C(C &&c) {
cout << " Move constructor: " << (intptr_t)this << endl;
this->ptr = c.ptr;
c.ptr = nullptr;
}
// Doesn't make sense! why? we have to update c's ptr into nullptr.
/*
C(const C &&c) {
cout << "(Const?) Move constructor: " << (intptr_t)this << endl;
this->ptr = c.ptr;
c.ptr = nullptr; // this is impossible!
} // ~C
*/
};
ostream &operator <<(ostream &out, C &c) {
out << *c.ptr;
return out;
}
class Container {
public:
C *buf;
size_t buf_size;
size_t filled;
Container() {
buf_size = 1000;
filled = 0;
buf = (C *)operator new(buf_size * sizeof(C)); // returns void*
}
~Container() {
for (size_t i = 0; i < filled; i++)
buf[i].~C();
operator delete(buf);
//delete buf; <- this doesn't work.
}
void push_back(const C &c) {
cout << "(push_back called)" << endl;
new (&buf[filled]) C(c);
filled++;
}
void push_back2(C c) {
cout << "(push_back2 called)" << endl;
new (&buf[filled]) C(c);
filled++;
}
void push_back3(C c) {
cout << "(push_back3 called)" << endl;
new (&buf[filled]) C(std::move(c));
filled++;
}
void emplace_back(C && c) {
cout << "(emplace_back called)" << endl;
new (&buf[filled]) C(c); // This calls copy constructor of C.
filled++;
}
void emplace_back2(C && c) {
cout << "(emplace_back2 called)" << endl;
new (&buf[filled]) C(std::forward<C>(c));
filled++;
}
};
int main() {
Container cont;
cout << "----Container::push_back" << endl;
C cc1(1);
cont.push_back(cc1);
/* Constructor: 140737261053008
push_back called
Copy constructor: 140737134595696 */
cout << "----Container::push_back2" << endl;
C cc2(2);
cont.push_back2(cc2);
/* Constructor: 140737261053016
Copy constructor: 140737261053104
push_back2 called
Copy constructor: 140737134595704
Destructor: 140737261053104 */
cout << "----Container::push_back3" << endl;
C cc3(3);
cont.push_back3(cc3);
/* Constructor: 140737261053024
Copy constructor: 140737261053104
push_back3 called
Move constructor: 140737134595712
Destructor: 140737261053104 */
cout << "----Container::emplace_back" << endl;
C cc11(11);
// cont.emplace_back(cc11) <- compilation error!
cont.emplace_back(std::move(cc11));
/* Constructor: 140737261053032
emplace_back called
Copy constructor: 140737134595720 */
cout << "----Container::emplace_back2" << endl;
C cc12(12);
cont.emplace_back2(std::move(cc12));
/* Constructor: 140737261053040
emplace_back2 called
Move constructor: 140737134595728 */
cout << endl;
for (size_t i = 0; i < cont.filled; i++) {
cout << cont.buf[i] << " , ";
}
cout << endl;
cout << endl;
cout << "-------" << endl;
cout << endl;
vector<C> v;
v.reserve(16);
cout << "----vector::push_back" << endl;
C vc1(10);
v.push_back(vc1);
/* Constructor: 140737261053048
Copy constructor: 140737134605040 */
cout << "----vector::emplace_back(C)" << endl;
v.emplace_back(C(20));
/* Constructor: 140737261053056
Move constructor: 140737134605048
Destructor: 140737261053056 */
cout << "----vector::emplace_back(int)" << endl;
v.emplace_back(30);
/* Constructor: 140737134605056 */
cout << endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment