Где использовать std::move для строк?
Я читал этот пост.
И я дошел до следующего кода.
Я размышлял:
Является
std::move
полезно для строк (при условии, что строка достаточно длинная)?Это делает недействительной предыдущую строку?
Где я должен его использовать, а где нет?
,
class Name
{
public:
Name(std::string firstName, std::string lastName)
: firstName_(std::move(firstName))
, lastName_(std::move(lastName)) {}
void print() const
{
std::cout << lastName_ << ", " << firstName_ << '\n';
}
private:
std::string firstName_;
std::string lastName_;
};
Моя техника всегда использовала
constructor(const std::string& argument): field(argument)
2 ответа
Фраза принятия параметров по значению имеет смысл, когда используется значение подвижного типа. Под потреблением значения я подразумеваю, что значение передается чему-то, что требует его собственной копии значения. Причина здесь в следующем:
- Когда аргумент передается по значению, копия может быть исключена, например, когда аргумент является результатом вызова другой функции. Даже когда копия не может быть удалена, аргумент потенциально может выглядеть как временный (например, используя
std::move(arg)
). - Поскольку значение передается в функцию, т. Е. Функция уже владеет копией, это значение можно пересылать туда, где оно необходимо.
- В худшем случае аргумент копируется, но, так как значение в любом случае необходимо, необходимо создать копию из
T const&
параметр, и дополнительная операция перемещения считается сравнительно дешевой.
Таким образом, ожидается, что в худшем случае может быть небольшая дополнительная работа, но в обычном случае работы существенно меньше, поскольку выполняется только одна операция перемещения вместо копирования.
За std::string
Аргумент немного сложнее, чем для других подвижных типов, из-за довольно распространенной оптимизации коротких строк: вместо нескольких операций с указателями может потребоваться передача байтов. Однако на практике копирование короткой строки или указателей фактически memcpy()
потенциально может сопровождаться операцией, указывающей, что источник операции перемещения больше не содержит строку, которую необходимо освободить.
Таким образом, простое правило
При использовании подвижного объекта принимайте аргумент по значению и перемещайте объект, а не передавайте аргумент через
T const&
и создайте копию, чтобы использовать результат.
При перемещении строки расходуется старое значение:
std::string sa = "Was the string";
std::string sb = std::move(sa);
std::cout << "Old [" << sa << "] new [" << sb << "]" << std::endl;
Вывод: Старый [] новый [Была строка]
Я предполагаю, что старое значение переходит в новую строку без копирования. Это должно быть эффективным, когда вам нужно назначить строковое поле в некоторой структуре для передачи в качестве параметра, как в ROS:
std::string my_message = method_that_returns_just_a_string();
std_msgs::String message;
message.data = std::move(my_message);
my_message теперь будет содержать некое «допустимое неопределенное значение». Выходные данные примера содержат пустую строку, но вы не должны полагаться на это.
Это не будет лишним клонированием, может быть, 1 Мб XML.