Почему они не позвонили std::string stdDevString = std::string(device_string);
в одну строку?
Нет веских причин для того, что они сделали. Учитывая конструктор std::string::string(const char*)
, вы можете просто использовать любой из:
std::string stdDevString = device_string;
std::string stdDevString(device_string);
std::string stdDevString{device_string}; // C++11 { } syntax
Двухступенчатая конструкция по умолчанию, тогда присваивание - это просто (плохой) стиль программиста или недосмотр. Без оптимизации, это делает немного ненужной конструкции, но это все еще довольно дешево. Скорее всего, это устранено оптимизацией. Не важно - сомневаюсь, упомянул бы я об этом в обзоре кода, если бы он не был в чрезвычайно чувствительной к производительности области, но определенно лучше отложить объявление переменных до тех пор, пока не будет доступно полезное начальное значение для их конструирования, локализации его все в одном месте: он не только менее подвержен ошибкам и перекрестным ссылкам, но и минимизирует область действия переменной, упрощая обоснование ее использования.
Чтобы гарантировать, что строка C внутри stdDevString
останется нулевой, независимо от того, что завершено?
Нет - это не имело значения. Начиная с C ++ 11, внутренний буфер в stdDevString
будет храниться с NUL-ограничением независимо от того, какой конструктор используется, в то время как для C ++ 03 не обязательно завершается - см. Подробный заголовок C ++ 03 ниже - но есть нет гарантий независимо от того, как выполняется строительство / назначение.
Потому что, насколько я знаю, при инициализации std::string
для строки C, которая не завершена нулем, все равно будут возникать проблемы.
Вы правы - любой из перечисленных вариантов построения будет только копировать текст ASCIIZ в std::string
- с учетом первого NUL ('\0'
) терминатора. Если массив char не завершен NUL, будут проблемы.
(Это отдельная проблема для того, чтобы буфер внутри std::string
оставался NUL завершенным - обсуждалось выше).
Обратите внимание, что есть отдельный конструктор string(const char*, size_type)
, который может создавать строки со встроенными NUL и не будет пытаться читать дальше, чем было сказано (Constructor (4) здесь )
C ++ 03 std :: строки не гарантированы внутренним NUL-завершением
Каким бы образом не создавался и не инициализировался std::string
, до C ++ 11 Стандарт не требовал завершения NUL в буфере строки. std::string
лучше всего представлять как набор потенциально непечатаемых (условно говоря, двоичных в смысле ввода / вывода ftp / file) символов, начинающихся с адреса data()
и продолжающихся до size()
символов. Итак, если у вас было:
std::string x("help");
x[4]; // undefined behaviour: only [0]..[3] are safe
x.at(4); // will throw rather than return '\0'
x.data()[4]; // undefined behaviour, equivalent to x[4] above
x.c_str()[4]; // safely returns '\0', (perhaps because a NUL was always
// at x[4], one was just added, or a new NUL-terminated
// buffer was just prepared - in which case data() may
// or may not start returning it too)
Обратите внимание, что API-интерфейсу std :: string требуется c_str()
для возврата указателя на значение, оканчивающееся NUL. Для этого он может либо: