Elementor Header #8

33. Неизменяемость строк

1. Введение

В C++ строки могут быть как изменяемыми, так и неизменяемыми. Разбираться в их различиях и ошибках, связанных с их использованием, важно для написания надёжного кода. В этом уроке мы обсудим неизменяемость строк, распространённые ошибки, связанные с их использованием, и предложим тестовое задание.

2. Что такое неизменяемость строк?

Неизменяемость строк означает, что после их создания содержимое строки не может быть изменено. В C++ стандартная библиотека предоставляет несколько типов строк, среди которых std::string является изменяемым типом, а строковые литералы — неизменяемыми.

Пример строки с неизменяемым содержимым:

				
					constchar* immutableStr = "Hello, world!";

				
			

В данном примере строка "Hello, world!" — это строковый литерал, который хранится в памяти как неизменяемый массив символов. Изменение этого массива может привести к неопределённому поведению.

3. Примеры распространённых ошибок с неизменяемыми строками

Попытка изменить строковый литерал:

				
					constchar* str = "Hello";
str[0] = 'h';  // Ошибка: изменение строкового литерала
				
			

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

Неправильное использование const с строковыми литералами:

				
					char* str = "World";  // Ошибка: строковый литерал должен быть константным
				
			

char* подразумевает изменяемость, что противоречит неизменяемости строковых литералов. Нужно использовать const char*.

Некорректное управление динамическими строками:

				
					char* str = new char[6];
strcpy(str, "Hello");
str[0] = 'h';  // Это допустимо, но важно не забывать освобождать памятьdelete[] str;

				
			

Здесь мы изменяем содержимое строки, выделенной динамически, что допустимо. Но забыв о delete[], мы утечем память.

Ошибки при использовании строковых функций:

				
					char str[10];
strcpy(str, "A very long string");  // Ошибка: переполнение буфера
				
			

str не имеет достаточно места для строки, и это может привести к переполнению буфера.

Заключение

Неизменяемость строк важна для обеспечения безопасности и корректности работы с текстовыми данными. Понимание различий между изменяемыми и неизменяемыми строками помогает избегать распространённых ошибок, таких как изменение строковых литералов или переполнение буфера. При работе с динамическими строками важно следить за выделением и освобождением памяти, чтобы избежать утечек.

4. Тестовое задание

Напишите программу на C++, которая:

  1. Создаёт строковый литерал и выводит его на экран.
  2. Создаёт изменяемую строку, инициализирует её значением и изменяет один из символов.
  3. Использует динамически выделенную строку, инициализирует её значением и выводит результат на экран.
  4. Освобождает память, выделенную для динамической строки.

Примерный код:

				
					#include <iostream>
#include <cstring>

int main() {
    // 1. Строковый литерал
    constchar* literalStr = "Hello, immutable world!";
    std::cout << "Литерал: " << literalStr << std::endl;

    // 2. Изменяемая строка
    char mutableStr[] = "Hello, mutable world!";
    mutableStr[0] = 'h';  // Изменение первого символа
    std::cout << "Изменяемая строка: " << mutableStr << std::endl;

    // 3. Динамическая строка
    char* dynamicStr = newchar[20];
    strcpy(dynamicStr, "Hello, dynamic world!");
    std::cout << "Динамическая строка: " << dynamicStr << std::endl;

    // 4. Освобождение памяти
    delete[] dynamicStr;

    return 0;
}

				
			

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

logo