Конструктор перемещения и назначение перемещения
Я читал книгу Бьярна Страуструпа (создатель C++) "4-й выпуск языка программирования C++" и изучал конструкторы и назначения перемещений.
В книге для вектора класса (см. 1 для заголовка ниже) он показывает, как реализовать конструктор перемещения (см. 2 ниже), и говорит, что назначение перемещения реализовано аналогичным образом, но не показывает, как. Я сам выполнил назначение перемещения (см. 3 ниже), и все, кажется, работает нормально, однако я не уверен, что выполнил это правильно.
Я не получаю никаких ошибок и посмотрел на многих примерах, но я не могу подтвердить его правильность для моего конкретного класса. Может кто-то имел опыт работы с C++, пожалуйста, посмотрите на мой код и прокомментируйте, если он правильный?
РЕДАКТИРОВАТЬ: Также см. 4 для конструкторов и деструкторов.
Спасибо за ваше время.
PS: любые полезные советы или модификации приветствуются
1) Заголовочный файл класса:
#ifndef VECTOR_H
#define VECTOR_H
#include <cstdlib>
#include <iostream>
#include <stdexcept>
using namespace std;
template<typename T>
class Vector {
public:
// constructors
Vector(int s);
Vector(std::initializer_list<T>);
// destructor
~Vector();
// copy constructor and copy assignment
Vector(Vector&);
Vector<T>& operator=(Vector&);
// move constructor and move assignment
Vector(Vector&&);
Vector<T>& operator=(Vector&&);
// operators
T& operator[](int);
const T& operator[](int) const; // the second const means that this function cannot change the state of the class
// we define operator[] the second time for vectors containing constant members;
// accessors
int getSize();
private:
int size;
T* elements;
};
#endif /* VECTOR_H */
2) Переместить конструктор (реализован так же, как и книга):
// move constructor
template<typename T>
Vector<T>::Vector(Vector&& moveme) : size{moveme.size}, elements{moveme.elements}
{
moveme.elements = nullptr;
moveme.size = 0;
}
3) Переместить задание (не уверен, правильно ли):
// move assignment
template<typename T>
Vector<T>& Vector<T>::operator=(Vector&& moveme)
{
delete[] elements; // delete old values
elements = moveme.elements;
size = moveme.size;
moveme.elements = nullptr;
moveme.size = 0;
return *this;
}
4) Конструкторы и деструкторы:
#include <array>
#include "Vector.h"
// constructors
template<typename T>
Vector<T>::Vector(int s) {
if(s<0) throw length_error{"Vector::Vector(int s)"};
// TODO: use Negative_size{} after learning how to write custom exceptions
this->size = s;
this->elements = new T[s];
}
template<typename T>
Vector<T>::Vector(std::initializer_list<T> list) : size(list.size()),
elements(new T[list.size()])
{
copy(list.begin(), list.end(), elements);
}
// destructor
template<typename T>
Vector<T>::~Vector()
{
delete[] this->elements;
}
1 ответ
Поскольку на этот вопрос ответили в комментариях, я подумал, что последую совету мета: Вопрос без ответов, но проблема решена в комментариях (или расширена в чате), и напишу короткую вики-страницу сообщества, чтобы закрыть и ответить на вопрос.
Я также добавлю полезную дополнительную информацию и советы от других пользователей, которые присоединились к обсуждению в комментариях.
Bo Persson ответил и предоставил дополнительную информацию о размещении шаблона:
Назначение перемещения кажется разумным, за исключением того, что размещение шаблонов в файле cpp позволяет использовать их только в этом файле cpp. См. Почему шаблоны могут быть реализованы только в заголовочном файле?
Rakete1111 разъясняет Rakete1111 заблуждение относительно семантики перемещения:
std:: move! = семантика перемещения У вас есть семантика перемещения, в которой можно переместить значения (используя конструктор перемещения) вместо копирования. std::move - это просто средство, позволяющее включить семантику перемещения (например, с помощью конструктора перемещения) для типов, которые не являются значениями.
Post Self поднимает вопрос оптимизации возврата с Post Self, и я отвечаю:
... Кроме того, действительно ли нет никакой оптимизации возвращаемого значения, если у вас нет перегруженных каторов / назначений перемещения? -kim366
Кажется, что в примере (см. Функцию ниже) он говорит, что
z = x + y + z
дважды скопирует возвращаемый результат: "Если вектор большой, скажем, 10000 удваивается, это может быть неловко". Но "Учитывая это определение, компилятор выберет конструктор перемещения для реализации переноса возвращаемого значения..." Он изобрел C++, так что я просто не пойму его слова:).Vector operator+(const Vector& a, const Vector& b) { if (a.size()!=b.size()) throw Vector_size_mismatch{}; Vector res(a.size()); for (int i=0; i!=a.size(); ++i) res[i]=a[i]+b[i]; return res; }
- хаммерамр(Пример был взят из книги Бьярна Страуструпа "Язык программирования C++, 4-е издание")
Смотрите также Что такое иероглиф копирования и обмена? Джайв Дадсон
Надеюсь, что люди найдут это полезным и спасибо за тех, кто принял участие.