Ниже приведен пример моего типичного кода. Есть много объектов, которые выглядят так:
struct Config
{
Config();
Config(const std::string& cType, const std::string& nType); //additional variables omitted
Config(Config&&) = default;
Config& operator=(Config&&) = default;
bool operator==(const Config& c) const;
bool operator!=(const Config& c) const;
void doSomething(const std::string& str);
bool doAnotherThing(const MyOtherObject& obj);
void doYetAnotherThing(int value1, unsigned long value2, const std::string& value3, MyEnums::Seasons value4, const std::vector<MySecondObject>& value5);
std::string m_controllerType;
std::string m_networkType;
//...
};
//...
Config::Config(const std::string& cType, const std::string& nType) :
m_controllerType(cType),
m_networkType(nType)
{
}
Мои мотивы и общее понимание предмета:
- использовать константные ссылки в конструкторах и методах, чтобы избежать двойного копирования при передаче объектов.
- простых типов - передача по значению; классы и структуры - проходите по константной ссылке (или простой ссылке, когда мне нужно изменить их)
- заставляет компилятор создавать
default
конструктор перемещения и задание перемещения, чтобы он мог выполнять свою причудливую магию и одновременно позволять избежать написания скучных ctor() : m_v1(std::move(v1)), m_v2(std::move(v2)), m_v3(std::move(v3)) {}
.
- если он работает плохо, используйте libc и raw-указатели, затем оберните его в классе и напишите комментарий.
У меня сильное чувство, что по эмпирическим правилам они несовершенны и просто неверны.
После прочтения cppreference, Скотта Майерса, стандарта C ++, Страуструпа и т. Д. Я чувствую: «Да, я понимаю каждое слово здесь, но оно по-прежнему не имеет никакого смысла». Единственное, что я, король, понял, это эта семантика перемещения имеет смысл, когда мой класс содержит не копируемые типы, такие как std::mutex
и std::unique_ptr
.
Я видел много кода, где люди передают сложный объект по значению, например, большие строки, векторы и пользовательские классы - я верю, что именно здесь происходит семантика перемещения, но, опять же, как вы можете передать объект в функцию двигаться? Если я прав, он оставил бы объект в «своего рода нулевом состоянии», что сделало бы его непригодным для использования.
Итак, вопросы:
Правильно выбрать между передачей по значению и передачей по ссылке?
- Нужно ли предоставлять конструкторы копирования и перемещения?
- Нужно ли явно писать перемещение и копировать конструкторы? Могу ли я использовать = default
? Мои классы в основном являются объектами POD, поэтому здесь нет сложных входов в систему.
- При отладке я всегда могу написать std::cout << "move\n";
или std::cout << "copy\n";
в конструкторах своих классов, но как мне узнать, что происходит с классами из stdlib
?
P.S. Может показаться, что это крик отчаяния (это так), а не действительный вопрос SO. Я просто не знаю, чтобы сформулировать свои проблемы лучше, чем это.