У меня есть класс с членом Glib :: ustring (если вы не знакомы с ним, предположите, что это std :: string), который, как ожидается, будет содержать длинную строку, т. Е. Как минимум один абзац, может быть, еще несколько. Может быть, даже более 10 пунктов. Строка планируется отображать в графическом интерфейсе, поэтому, возможно, в будущем она будет сохранена в буфере текстового виджета, но пока это просто объект-член строки моего класса C ++.
Вопрос в том, как передать строку в конструктор и как передать ее в метод set_string (). Длинная строка означает большую копию, поэтому хорошим решением было бы взять ссылку на rvalue и std :: переместить аргумент в объект-член. Но я также не хочу, чтобы интерфейс класса был удивительным и сложным в использовании / понимании. Вы знаете, правило наименьшего удивления.
Вот я и подумал, каково ожидаемое / общее решение в этом случае?
(для метода сеттера есть еще один вариант: поскольку редактирование выполняется в графическом интерфейсе, просто позвольте графическому интерфейсу редактировать строку напрямую, и тогда единственное использование метода сеттера — полностью заменить строку программно, например, сбросить ее или отменить недавнее редактирование )
class MyClass
{
public:
explicit MyClass (Glib::ustring str);
void set_string (Glib::ustring str);
private:
Glib::ustring str;
}
(Я видел код существующих библиотек, например, gtkmm, принимающий строки по константной ссылке, но я также видел сообщения SO с ответами, в которых говорилось о передаче по значению для оптимизации)
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/
Ваша функция должна принять string
по значению, предполагая, что ваш string
имеет эффективный Move-конструктор.
Когда вы ожидаете, что строка будет длинной, вызывающая сторона вызывает std::move
и передает значение установщику / конструктору. Это не удивительно, потому что std::move
довольно ясно показывает, что вы перемещаете данные.
Если ваша система имеет не более чем скромное количество параллелизма, и вы редко изменяете строки (на самом деле, большинство строк разделяются гораздо больше, чем модифицируются), общие указатели на неизменяемые строки на самом деле довольно полезный шаблон. (Совместно используемые данные записи — это число ссылок, поэтому при высоком уровне параллелизма может возникнуть конфликт)
Я бы пошел за ссылками (не только передавая их, но и сохраняя ссылку). Тем не менее, сеттер должен переустановить ссылку, что невозможно. Если вам действительно нужно изменить строку после построения, вы должны использовать указатели (возможно, умные указатели).
В зависимости от окружающего кода вы можете использовать общее владение строкой. В этом случае я бы использовал std::shared_pointer<GLib::ustring>
, Если вам нужен сеттер. (В противном случае, ссылка лучше.)
Обратите внимание, что «некоторые абзацы» не являются очень длинный строки. В пользовательских интерфейсах задержка в пару миллисекунд, скажем, при загрузке какого-либо текстового файла, вполне допустима. Как всегда: пожалуйста, сначала профилируйте свой код, определите узкое место, затем оптимизируйте, если вам нужно, чтобы он был быстрее.