Да, это чудеса C++ и понимание:
- Время жизни объектов
- Эта строка является классом, а буквальное символьные массивы не являются «строками».
- Что происходит с неявными конструкторами.
В любом случае строка является классом, «Hey» на самом деле представляет собой просто массив символов. Поэтому, когда вы создаете Foo с «Hey», который хочет ссылку на строку, он выполняет так называемое неявное преобразование. Это происходит потому, что string
имеет неявный конструктор из массивов символов.
Теперь на время жизни объекта. Построив эту цепочку для вас, где она живет и какова ее продолжительность жизни. Ну собственно для значения этого вызова, вот конструктор Foo и все, что он называет. Таким образом, он может вызывать всевозможные функции целиком и эта строка действительна.
Однако, как только этот вызов завершен, объект истекает.К сожалению, вы сохранили в своем классе ссылку на const, и вам разрешено. Компилятор не жалуется, потому что вы можете сохранить ссылку на const для объекта, который будет жить дольше.
К сожалению, это неприятная ловушка. И я помню, как только я преднамеренно отдал своего конструктора, который действительно хотел ссылку на const, неконстантную ссылку с целью обеспечить точно, чтобы эта ситуация не возникала (и не получала бы временную). Возможно, это не лучший способ обхода, но он работал в то время.
Ваш лучший вариант в большинстве случаев - просто скопировать строку. Это дешевле, чем вы думаете, если вы действительно не обрабатываете много и много. В вашем случае это, вероятно, на самом деле ничего не скопирует, и компилятор будет тайно перемещать копию, которую он сделал в любом случае.
Вы также можете взять неконстантную ссылку на строку и «своп» это в
С C++ 11 есть еще один вариант использования перемещения семантики, что означает, что строка, переданная в станет " приобретенный ", сам признал недействительным. Это особенно полезно, когда вы хотите использовать временные ряды, которые являются вашим примером (хотя главным образом временные строятся с помощью явного конструктора или возвращаемого значения).
Потому что первый указывает на временную строку, которая была уничтожена сразу после вызова конструктора Foo. (Временная std :: строка, созданная из (c-) строкового литерала «Hey») – Borgleader
Просто указывая на это, если вы используете 'const char *', первый случай будет в порядке, поскольку строковые литералы живут вечно. –
Btw, если ваш конструктор принимал неконстантный параметр, первая версия не скомпилировалась, потому что вы не можете привязать временный объект к неконстантическому ref. – Borgleader