У меня есть простой класс с несколькими тривиальными членами и без каких-либо выделений. Я планирую добавить конструктор/назначение перемещения. Эти примитивы не будут более эффективными, чем обычные.
Вопрос первый: имеет ли смысл это делать, чтобы сделать мой класс более универсальным?
Существует внутренний список, связывающий объекты класса.
Вопрос второй: в каком состоянии мне следует оставить класс, из которого был перемещен: в списке или удален из списка? Планирую удалить его из списка.
Обновление: есть несколько комментариев по использованию ходов, генерируемых компилятором. Я не могу этого сделать, потому что есть внутренний список, о котором мне нужно позаботиться.
Итак, это либо ручные ходы, либо ничего. Фрагмент возможного кода ниже, многопоточности нет.
class A {
public:
static void Run() {
A* cur = list_;
while(cur) {
cur->DoWork();
cur = cur->next_;
}
}
virtual ~A() { Remove(); }
A() : next_(), data_(), in_list_() {
}
A(int data) : next_(), data_(data), in_list() {
Insert();
}
A(A const& other) : next_(), data_(other.data_), in_list() {
Insert();
}
A(A&& other) : next_(), data_(other.data_), in_list() {
other.Remove();
Insert();
}
A& operator=(A const& other) {
if (this != &other) {
data_ = other.data_;
Insert();
}
return *this;
}
A& operator=(A&& other) {
if (this != &other) {
data_ = other.data_;
other.Remove();
Insert();
}
return *this;
}
private:
void DoWork() { <do-something-important-with-data>; }
void Insert() {
if (_in_list) {
return;
}
...;
in_list_ = true;
}
void Remove() {
if (!_in_list) {
return;
}
...;
in_list_ = false;
};
A* next_;
int data_;
bool in_list_;
static A* list_;
};
пожалуйста, по одному вопросу на вопрос. И пожалуйста, покажите код, а не описывайте его.
Полагаю, вы имеете в виду «эффективный», а не «эффективный».
Второй вопрос звучит так, будто вы не поняли семантику хода.
обязательно прочитайте также о правиле нуля.
Перемещение тривиального типа ничем не отличается от его копирования. Создаваемых компилятором конструкторов копирования/перемещения по умолчанию и операторов копирования/перемещения будет достаточно.
другими словами, ход уже возвращается к копии. Нет смысла снова заставлять ваш класс реализовывать это резервное поведение.
Образовательный просмотр стоит потраченного времени: Презентация Говарда Хиннанта «Все, что вам нужно знать о семантике перемещения»
Вероятно, в этом примере достаточно, но общая рекомендация — отказаться от ...
и предоставить пример кода, который люди смогут использовать в своих инструментах и поиграть с ним. Удивительно, какие интересные вещи могут получить люди, если вы приведете полный пример. Но не переусердствуйте; придерживаться минимального воспроизводимого примера .
@user4581301 user4581301 Мой вопрос не в том, «как это сделать?». Мой вопрос: имеет ли это смысл?
Начнем с того, что ваш дизайн ошибочен. Объект не должен заботиться о том, является ли он частью списка. Кроме того, ограничение себя одним списком далеко не является универсальным.
@molbdnilo Извините, приложение требует наличия объектов в списке.
@ uuu777 Конечно, объекты должны быть в списке. Это не означает, что существует только один список или что вам нужен флаг, чтобы отслеживать, является ли узел частью какого-либо списка или нет.
После обсуждения в комментариях (всем спасибо), кажется, я могу сам ответить на этот вопрос: (1) реализовать правило пяти — это хорошая идея только для поддержки unique_ptr, (2) исходный объект ход не должен быть в списке после его завершения.
Не добавляйте ничего из этого (конструктор копирования/перемещения/назначения), если в них нет необходимости. Не уверен, что вы подразумеваете под «более общим», но переопределение функций класса, которые компилятор сгенерирует для вас, не делая ничего полезного, для меня не имеет смысла.