Top.Mail.Ru
Ответы

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).Я запутался, даже не знаю как сформулировать, надеюсь кто то поможет.

По дате
По Рейтингу
Аватар пользователя
Высший разум
5мес
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
 #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"); 
} 
Аватар пользователя
Мудрец
5мес

move assign — присваивание возвращенного функцией create_array значения объекту wr
DArray copy — возврат копии из оператора присваивания перемещением (вы сами так зачем-то сделали)
Destr — разрушается возвращенное значение, которое было создано конструктором копирования на предыдущем шаге
Destr — разрушается значение, которое было перемещено
Destr — разрушается wr