я ответил здесь
В этот ответ я вставил одну вещь: Ни один из них не использует оператор присваивания .
Хотя краткое объяснение специфической для строки вещи. std::string
имеет конструктор, принимающий один аргумент, который принимает char const*
:
// simplified to a normal class declaration. std::string actually
// is a template instantiation.
class string {
public:
string(char const* str) {
// copy over...
}
};
Теперь вы видите, что у конструктора есть указатель на символ (ы). Так что он может принимать строковый литерал. Я думаю, что следующий случай очевиден:
string s("hello");
Он вызовет конструктор напрямую и тем самым инициализирует s
. Это называется прямой инициализацией .
Другой способ инициализации переменной называется copy initialization . Стандарт говорит, что в случае инициализации копии, когда инициализатор имеет , а не тип объекта, который он инициализирует, инициализатор преобразуется в правильный тип.
// uses copy initialization
string s = "hello";
Во-первых, давайте сформулируем типы
s
имеет тип std :: string
"hello"
- это массив, который в этом случае снова обрабатывается как указатель. Поэтому мы будем рассматривать его как char const*
.
Компилятор ищет два способа сделать преобразование.
- Есть ли в std :: string конструктор преобразования ?
- Имеет ли инициализатор тип с функцией оператора преобразования, возвращающей
std::string
?
Он создаст временный std::string
одним из тех способов, который затем используется для инициализации объекта s
с помощью std::string
копирующего конструктора . И он видит, что std::string
имеет конструктор преобразования, который принимает инициализатор. Так что он использует это. В конце концов, это фактически так же, как
std::string s(std::string("hello"));
Обратите внимание, что форма, используемая в вашем примере, которая вызвала все это
std::string s = "hello";
определяет неявное преобразование . Вы можете пометить конструктор, принимающий char const*
как явный для ваших типов, если вам интересно узнать о правилах инициализации вашего материала, и он не позволит использовать соответствующий конструктор в качестве конструктора преобразования больше:
class string {
public:
explicit string(char const* str) {
// copy over...
}
};
При этом его инициализация с использованием copy initialization
и char const*
фактически запрещена (и в других местах)!
Так вот, это было, если компилятор не поддерживает удаление временных файлов в разных местах. Компилятору разрешается предполагать, что конструктор копирования копирует в этом контексте и может исключить дополнительную копию временной строки и вместо этого создать временную строку std :: string непосредственно в инициализированном объекте. Однако конструктор копирования должен быть доступен, в частности. Таким образом, инициализация копии будет недействительной, если вы сделаете это
class string {
public:
explicit string(char const* str) {
// copy over...
}
private: // ugg can't call it. it's private!
string(string const&);
};
Теперь на самом деле допустим только случай прямой инициализации.