Самый простой способ ответить на ваш вопрос - сломать то, что происходит в обоих случаях.
testclass(const string& sref)
testclass t1("constStringRef");
сначала создает временный string
объект из const char*
- конструктор вызывается, временный
string
объект привязан к const string&
аргумента конструктора
name
является бесцельно по-умолчанию, так как вы не использовали список инициализаторов конструктора (подробнее об этом позже)
string::operator =
называется, что делает копию const string&
аргумента
Итого: 1 экземпляр.
testclass(string str)
testclass t1("constStringRef");
первый создает временный string
объект из const char*
- конструктор называется - то, что происходит, зависят от C++ версии вы используете:
- C++ 03: временный объект
string
копируется в аргумент конструктора
- C++ 11: временный перемещен в аргумент конструктора
name
является бесцельно по-умолчанию, так как вы не использовали список инициализации конструктора
string::operator =
называется, что делает копию string
аргумента
Итого: 2 копии в C++ 03, 1 копия на C++ 11.
Исходя из этого, мы можем полагать, что const string&
лучше. Однако это относится только к C++ 03.
C++ 11 и переместить семантика
В C++ 11, то лучше (в данном конкретном случае), чтобы передать строку по значению конструктора, а затем переместить аргумент в ваш член класса:
testclass(string str){
name = std::move(str);
}
Давайте посмотрим, что происходит сейчас:
testclass t1("constStringRef");
первый создает временный string
объект из const char*
- конструктор вызывается, временным это переехал в аргумент конструктора
name
является бесцельно по-умолчанию, так как вы не использовали список инициализации конструктора
string::operator =
называется, но на этот раз перемещениеstring
аргумент в name
Итого: 0 коп у!
Это все нормально с rvalues, но сохраняет ли это значение для lvalues?
string s = "..."; // s has already been constructed some time ago
testclass t1(s); // what happens during this call?
для конструктора, который принимает const string&
(как в C++, 03 и C++, 11):
s
связан с const string&
аргумента
name
является бесполезно построенный по умолчанию, поскольку вы не использовали список инициализаторов конструктора
string::operator =
, составление копии аргумента const string&
- Всего: 1 копию.
для конструктора, который принимает string
, а затем перемещает его (только в C++ 11):
s
копируется в string
аргумент
name
является по умолчанию бесполезно построенного так как вы не использовали список инициализаторов конструктора
string::operator =
вызывается, но на этот раз movingstring
аргумент в name
- Всего: 1 копию.
Обертывание его
В C++ 03, будь вы передаете именующее выражение или Rvalue не имеет значения, это всегда более эффективно использовать const string&
. Как уже упоминалось, вы можете перегрузить ваш конструктор, чтобы принять аргумент const char*
и тем самым избежать ненужной копии.
В C++ 11, если вы переместите аргумент в переменную-член, string
аргумент такой же, как const string&
аргумент для lvalues, но это является более эффективным для rvalues (копия не должна быть выполнена в все). Поэтому вы должны использовать pass-by-value, а затем переместить аргумент в переменную-член.
Последнее, но не менее, вы заметили, что я настаивал на бесцельно по умолчанию, построения name
. Чтобы избежать этого, используйте список инициализаторов конструктора, а не назначение в теле конструктора:
// C++03
testclass(const char* str) : name(str) {} // no copy
testclass(const string& sref) : name(sref) {} // 1 copy
// C++11
testclass(string str) : name(std::move(str)) {} // 1 copy for lvalues,
// no copy for rvalues
Все в вашем коде не имеет смысла. что такое 'n' и' s' ?! –
Вы должны попытаться скомпилировать код перед раздуванием его на StackOverflow! –
Извините, переименовал его, чтобы сделать его понятным и забыл переименовать задания. – TMK241