rvo и конструкторы c++ супер запутался
#include<iostream>
class DArray {
int* data{ nullptr };
int length{ 0 };
int capacity{ 0 };
public:
DArray(int size = 0) : length(0), capacity(size)
{
std::cout << "DArray create" << std::endl;
data = new int[capacity];
}
DArray(const DArray& other) : length(other.length), capacity(other.capacity)
{
std::cout << "DArray copy" << std::endl;
data = new int[capacity];
for (int i = 0; i < length; ++i)
data[i] = other.data[i];
}
DArray(DArray&& right) : length(right.length), capacity(right.capacity)
{
std::cout << "move" << std::endl;
data = right.data;
right.data = nullptr;
}
DArray operator=(DArray&& right) {
if (this == &right) return *this;
delete data;
std::cout << "move assigm" << std::endl;
length = right.length;
capacity = right.capacity;
data = right.data;
right.data = nullptr;
return *this; // а если не написать?
}
const DArray& operator =(const DArray& other) {
if (this == &other) return *this;
std::cout << "Operator= " << std::endl;
length = other.length;
capacity = other.capacity;
delete data;
data = new int[capacity];
for (int i = 0; i < length; ++i)
{
data[i] = other.data[i];
}
return *this;
}
~DArray() {
std::cout << "Destr" << std::endl;
delete[]data;
}
};
DArray create_array(int size) {
DArray ar(size);
return ar;
}
int main() { DArray wr;
wr = create_array(10);
} Я специально не поставил ссылку в копировании перемещением, чтобы до конца разобраться с работой конструкторов и операторов. Без rvo(может это не rvo, вроде там прямая инициализация без операторов присваивания и move assigm) у нас создается локальный объект, который мы возвращаем и у нас происходит copy или move для создания временного объекта, который должен попасть в operator=(&&) где произойдет финальное присваивание. Вот что выводится в консоль: DArray create
DArray create
move assigm
DArray copy
Destr
Destr
Destr
Вопрос: как это работает?? У меня происходит move assigm без копирования локал объекта и затем происходит копирование возвращаемого объекта, который я передал по значению и затем появляется еще 1 временный объект(я про 3 destr).Я запутался, даже не знаю как сформулировать, надеюсь кто то поможет.
#include <algorithm>
#include <iostream>
#include <memory>
#include <random>
using namespace std;
template<typename T>
class DinArray {
size_t length;
size_t buffer;
unique_ptr<T[]> uptr;
friend ostream& operator<<(ostream& out, const DinArray& da) {
for (auto x : da) out << x << ' ';
return out;
}
friend istream& operator>>(istream& inp, DinArray& da) {
for (auto& x : da) inp >> x;
return inp;
}
public:
~DinArray() = default;
DinArray()
: length(0), buffer(0), uptr(nullptr) {
}
DinArray(const size_t length, const T value = T{})
: length(length), buffer(length), uptr(make_unique<T[]>(length)) {
for (auto& x : *this) x = value;
}
DinArray(const initializer_list<T>& il)
: length(il.size()), buffer(length), uptr(make_unique<T[]>(length)) {
copy(il.begin(), il.end(), begin());
}
DinArray(const DinArray& da)
: length(da.size()), buffer(length), uptr(make_unique<T[]>(length)) {
copy(da.begin(), da.end(), begin());
}
DinArray(DinArray&& da) noexcept
: length(da.size()), buffer(length), uptr(move(da.uptr)) {
}
DinArray(const T* start, const T* stop)
: length(distance(start, stop)), buffer(length), uptr(make_unique<T[]>(length)) {
copy(start, stop, begin());
}
DinArray& operator=(const DinArray& da) {
if (this != &da) {
length = da.length;
buffer = da.buffer;
uptr.reset(new T[length]);
copy(da.begin(), da.end(), begin());
}
return *this;
}
DinArray& operator=(DinArray&& da) noexcept {
length = da.length;
buffer = da.buffer;
uptr.reset(new T[length]);
uptr = move(da.uptr);
return *this;
}
T& operator[](size_t i) { return uptr[i]; }
const T& operator[](size_t i) const { return uptr[i]; }
void sort() { std::sort(begin(), end()); }
size_t size() const { return length; }
size_t capacity() const { return buffer; }
void push_back(const T& value) {
if (length == buffer) {
auto tmp = *this;
buffer <<= 1;
uptr.reset(new T[buffer]);
copy(tmp.begin(), tmp.end(), begin());
}
uptr[length] = value;
++length;
}
void pop_back() { if (!empty()) { --length; } }
bool empty() const { return length == 0; }
T& front() { return *begin(); }
T& back() { return *(end() - 1); }
T* begin() { return uptr.get(); }
T* end() { return uptr.get() + length; }
const T* begin() const { return uptr.get(); }
const T* end() const { return uptr.get() + length; }
};
int main() {
DinArray<int> da{ 1, 3, 5, 7, 9 };
for (auto x : da) cout << x << ' ';
puts("");
da.push_back(11);
for (size_t i = 0; i < da.size(); ++i) cout << da[i] << ' ';
puts("");
system("pause > nul");
}
move assign — присваивание возвращенного функцией create_array значения объекту wr
DArray copy — возврат копии из оператора присваивания перемещением (вы сами так зачем-то сделали)
Destr — разрушается возвращенное значение, которое было создано конструктором копирования на предыдущем шаге
Destr — разрушается значение, которое было перемещено
Destr — разрушается wr