Ошибка в строке '\ 0' пусто при объединении - PullRequest
3 голосов
/ 23 марта 2019

Итак, я пытаюсь объединить простые строки и сделать последнее предложение.

int main()
{
    string I ("I");
    string Love ("Love");
    string STL ("STL,");
    string Str ("String.");
    string fullSentence = '\0';

    // Concatenate
    fullSentence = I + " " + Love + " " + STL + " " + Str;
    cout << fullSentence;

    return 0;
}

Здесь я не хотел, чтобы «fullSentence» ни с чем, поэтому я присвоил значение null, и оно дает мнеошибка.Нет определенного сообщения об ошибке, кроме следующего, который я совсем не понимаю ...:

Исключение, выданное в 0x51C3F6E0 (ucrtbased.dll) в упражнении_4.exe: 0xC0000005: Местоположение чтения нарушения доступа 0x00000000.произошло

Вскоре, когда я удаляю '\ 0', все работает просто отлично.Почему так?

Ответы [ 3 ]

3 голосов
/ 23 марта 2019

Мне кажется, это ошибка компилятора MSVC.

Утверждение:

string fullSentence = '\0';

не должно компилироваться.


Действительно, естьне является допустимым (неявным) конструктором от char (т.е. '\0') до std::string. Ссылка здесь .


Обратите внимание, что gcc и clang не принимают этот код как действительный. MSVC делает.


Почему это так?

Глядя на код сборки, MSVC компилирует этот оператор с помощью следующего конструктора:

std::string::string(char const * const);

Передав '\0' в качестве аргумента, он будет фактически преобразован в nullptr.

Итак:

Создает строку ссодержимое инициализируется копией строки символов с нулевым символом в конце, на которую указывает s.Длина строки определяется первым нулевым символом.Поведение не определено, если [s, s + Traits :: length (s)) не является допустимым диапазоном (например, , если s является нулевым указателем ).

Таким образом, ваш код неопределенного поведения.

1 голос
/ 23 марта 2019

Вы можете использовать отладчик, чтобы увидеть стек вызовов того, что произошло.Глядя на строковый класс здесь В вашем случае был вызван конструктор ниже:

basic_string( const CharT* s, const Allocator& alloc = Allocator() );

Согласно описанию конструктора (выделение мое) Создает строку с содержимым, инициализированным с помощью копия строки символов с нулем в конце , на которую указывает s.Длина строки определяется первым нулевым символом. Поведение не определено, если [s, s + Traits :: length (s)) не является допустимым диапазоном

в вашем случае диапазон пуст -> недействителен.

1 голос
/ 23 марта 2019

Поставьте "\0" вместо '\0'. В C ++ '' для символа, а "" для строки.

Это преобразование из char в нескалярный тип std::string

...