Parent directory
Makefile
intarray2.cpp
rvalue-test.cpp
CC = g++
CXX = g++
CFLAGS = -g -Wall
CXXFLAGS = -g -Wall -std=c++14 -fno-elide-constructors
executables = intarray2 rvalue-test
.PHONY: default
default: $(executables)
intarray2: intarray2.o
rvalue-test: rvalue-test.o
.PHONY: clean
clean:
rm -f *~ a.out core *.o $(executables)
.PHONY: all
all: clean default
#include <string>
#include <iostream>
class IntArray {
public:
IntArray() : sz{0}, cap{1}, a{new int[cap]} {}
~IntArray() {
delete[] a;
}
IntArray(const IntArray&) = delete;
IntArray& operator=(const IntArray&) = delete;
// This is how we can explicitly request compiler-generated versions:
// IntArray(const IntArray&) = default;
// IntArray& operator=(const IntArray&) = default;
/*
// Move constructor
IntArray(IntArray&& tmp) : sz{tmp.sz}, cap{tmp.cap}, a{tmp.a} {
tmp.sz = tmp.cap = 0;
tmp.a = nullptr;
std::cout << "move ctor" << std::endl;
}
*/
/*
// Move assignment
IntArray& operator=(IntArray&& tmp) {
if (this != &tmp) {
delete[] a;
sz = tmp.sz;
cap = tmp.cap;
a = tmp.a;
tmp.sz = tmp.cap = 0;
tmp.a = nullptr;
}
std::cout << "move assignment" << std::endl;
return *this;
}
*/
int& operator[](int i) { return a[i]; }
const int& operator[](int i) const { return a[i]; }
size_t size() const { return sz; }
size_t capacity() const { return cap; }
void push_back(int x) {
if (sz == cap) {
// Separate cap*=2 to provide strong exception guarantee
// int *a2 = new int[cap *= 2];
int *a2 = new int[cap * 2];
cap *= 2;
std::copy(a, a+sz, a2);
delete[] a;
a = a2;
}
a[sz++] = x;
}
private:
size_t sz;
size_t cap;
int *a;
};
std::ostream& operator<<(std::ostream& os, const IntArray& ia) {
for (size_t i = 0; i < ia.size(); i++) {
os << ia[i] << " ";
}
std::cout << "(cap=" << ia.capacity() << ")" << std::flush;
return os;
}
/*
IntArray createIntArray() {
IntArray tmp;
for (int i = 0; i < 20; i++) {
tmp.push_back(i);
std::cout << tmp << std::endl;
}
return tmp;
}
*/
int main() {
using namespace std;
// 1. Move construction
IntArray ia { /* createIntArray() */ };
cout << "ia: " << ia << endl;
/*
// 2. Move assignment
IntArray ia2;
ia2 = ia;
//ia2 = (IntArray&&)ia;
//ia2 = std::move(ia);
cout << "ia2: " << ia2 << endl;
cout << "ia: " << ia << endl;
*/
}
#include <iostream>
using namespace std;
struct X {
X() : d{100} {}
double d;
};
void f1(X& t) { t.d *= 2; cout << t.d << endl; }
void f2(const X& t) { cout << "can't change t" << endl; }
void f3(X&& t) { t.d *= 3; cout << t.d << endl; }
int main() {
X x; // x is an lvalue
f1(x); // passing an lvalue to X& --> ok
f2(x); // passing an lvalue to const X& --> ok
// f3(x); // passing an lvalue to X&& --> not ok
// f1( X{} ); // passing an rvalue to X& --> not ok
f2( X{} ); // passing an rvalue to const X& --> ok
f3( X{} ); // passing an rvalue to X&& --> ok
}