Consider the code bellow where a number of objects from class "MyType" are stored inside a vector, then this vector are passed to an object of class "VectorProcessor":
// to compile, run: g++ -Wall --std=c++17 test.cpp -o test
#include <vector>
#include <iostream>
using namespace std;
class MyType {
private:
int x;
public:
MyType(int a_x) {
this->x = a_x;
cout << "MyType constructor; x=" << this->x << endl;
}
~MyType() {
cout << "MyType destructor; x=" << this->x << endl;
this->x = 0;
}
MyType(const MyType &o) {
this->x = o.x +10;
cout << "MyType copy constructor; x=x'+10=" << this->x << endl;
}
MyType& operator=(const MyType& o) {
this->x = o.x +20;
cout << "MyType =copy constructor; x=x'+20=" << this->x << endl;
return *this;
}
MyType(MyType &&o) {
this->x = o.x + 30;
cout << "MyType move constructor; x=x'+30=" << this->x << endl;
}
MyType & operator=(MyType &&o) {
this->x = o.x + 40;
cout << "MyType =move constructor; x=x'+40=" << this->x << endl;
return *this;
}
friend ostream& operator<<(ostream& os, const MyType& s) {
return os << s.x;
}
};
template <typename T>
class VectorProcessor {
private:
const vector<T> &v;
public:
VectorProcessor(const vector<T> &a_lista): v{a_lista} {
cout << "VectorProcessor constructor" << endl;
}
VectorProcessor(const vector<T> &&a_lista): v(a_lista) {
cout << "VectorProcessor rvalue constructor" << endl;
}
const T& getLast() {
return this->v[this->v.size()-1];
}
};
int main() {
#if 1
// test (A)
vector<MyType> v{1,2,3,4,5};
VectorProcessor<MyType> r(v);
#else
// test (B)
VectorProcessor<MyType> r(vector<MyType>{1,2,3,4,5});
#endif
cout << "r.getLast(): " << r.getLast() << endl;
return 0;
}
If I enable "test A", the program output is:
MyType constructor; x=1
MyType constructor; x=2
MyType constructor; x=3
MyType constructor; x=4
MyType constructor; x=5
MyType copy constructor; x=x'+10=11
MyType copy constructor; x=x'+10=12
MyType copy constructor; x=x'+10=13
MyType copy constructor; x=x'+10=14
MyType copy constructor; x=x'+10=15
MyType destructor; x=5
MyType destructor; x=4
MyType destructor; x=3
MyType destructor; x=2
MyType destructor; x=1
VectorProcessor constructor
r.getLast(): 15
MyType destructor; x=11
MyType destructor; x=12
MyType destructor; x=13
MyType destructor; x=14
MyType destructor; x=15
And If I enable "test B", the program output is:
MyType constructor; x=1
MyType constructor; x=2
MyType constructor; x=3
MyType constructor; x=4
MyType constructor; x=5
MyType copy constructor; x=x'+10=11
MyType copy constructor; x=x'+10=12
MyType copy constructor; x=x'+10=13
MyType copy constructor; x=x'+10=14
MyType copy constructor; x=x'+10=15
VectorProcessor rvalue constructor
MyType destructor; x=11
MyType destructor; x=12
MyType destructor; x=13
MyType destructor; x=14
MyType destructor; x=15
MyType destructor; x=5
MyType destructor; x=4
MyType destructor; x=3
MyType destructor; x=2
MyType destructor; x=1
r.getLast(): 0
Then I ask: Without using pointers, or smart pointers,
1) How to avoid extra copying that occours in the objects from MyType class (for both test A and B)? 2) In the "test B", why the MyType destructor are called before r.getLast()? In other words, how to extent the lifetime of the temporary vector<MyType>{1,2,3,4,5}
to the end of block?
Aucun commentaire:
Enregistrer un commentaire