Herb Sutter все еще записывается вместе с Bjarne Stroustroup, рекомендуя const std::string&
как тип параметра; см. https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rf-in .
В любом из других ответов здесь нет ни малейшей ошибки: если вы передадите строковый литерал в параметр const std::string&
, он передаст ссылку на временную строку, созданную на лету для хранения символов буквального. Если вы сохраните эту ссылку, она будет недействительной после освобождения временной строки. Чтобы быть в безопасности, вы должны сохранить копию , а не ссылку. Проблема связана с тем, что строковые литералы - это типы const char[N]
, для которых требуется продвижение до std::string
.
Код ниже иллюстрирует ловушку и обходной путь вместе с небольшим вариантом эффективности - перегрузка с помощью метода const char*
, как описано в . Есть ли способ передать строковый литерал как ссылку в C ++ .
(Примечание: Sutter & amp; Stroustroup советует, чтобы, если вы сохраняете копию строки, также предоставляете перегруженную функцию параметром & amp; & amp; и std :: move ( ) it.)
#include
#include
class WidgetBadRef {
public:
WidgetBadRef(const std::string& s) : myStrRef(s) // copy the reference...
{}
const std::string& myStrRef; // might be a reference to a temporary (oops!)
};
class WidgetSafeCopy {
public:
WidgetSafeCopy(const std::string& s) : myStrCopy(s)
// constructor for string references; copy the string
{std::cout << "const std::string& constructor\n";}
WidgetSafeCopy(const char* cs) : myStrCopy(cs)
// constructor for string literals (and char arrays);
// for minor efficiency only;
// create the std::string directly from the chars
{std::cout << "const char * constructor\n";}
const std::string myStrCopy; // save a copy, not a reference!
};
int main() {
WidgetBadRef w1("First string");
WidgetSafeCopy w2("Second string"); // uses the const char* constructor, no temp string
WidgetSafeCopy w3(w2.myStrCopy); // uses the String reference constructor
std::cout << w1.myStrRef << "\n"; // garbage out
std::cout << w2.myStrCopy << "\n"; // OK
std::cout << w3.myStrCopy << "\n"; // OK
}
OUTPUT:
const char * constructor const std::string& constructor Second string Second string