Я изучаю С++ с самого начала, и я не получаю тему целых строк.
В чем разница между следующими тремя кодами?
-
std::string s = std::string("foo"); -
std::string s = new std::string("foo"); -
std::string s = "foo";
Я изучаю С++ с самого начала, и я не получаю тему целых строк.
В чем разница между следующими тремя кодами?
std::string s = std::string("foo");std::string s = new std::string("foo");std::string s = "foo";std::string s = std::string("foo");
Создает временный объект std::string, содержащий "foo" , затем присваивает его s. (Обратите внимание, что компиляторы могут уклоняться от временной. Временный elison в этом случае явно разрешен стандартом С++.)
std::string s = new std::string("foo");
Это ошибка компилятора. Выражение new std::string("foo") создает std::string в свободном хранилище и возвращает указатель на std::string. Затем он пытается присвоить возвращаемый указатель типа std::string* на s типа std::string. Конструкция класса std::string предотвращает это, поэтому сбой компиляции.
С++ не является Java. Это не так, как обычно создаются объекты, потому что если вы забудете delete возвращенный объект std::string, вы будете утечки памяти. Одним из основных преимуществ использования std::string является то, что он автоматически управляет базовым буфером строк, поэтому new - это своего рода поражения этой цели.
std::string s = "foo";
Это по существу то же самое, что и # 1. Он технически инициализирует новую временную строку, которая будет содержать "foo" , а затем присваивает ее s. Опять же, компиляторы, как правило, удаляют временные (и на самом деле почти все не-глупые компиляторы в настоящее время фактически исключают временные), поэтому на практике он просто создает новый объект с именем s на месте.
В частности, он вызывает конструктор преобразования в std::string, который принимает аргумент const char*. В приведенном выше коде конструктор преобразования должен быть не explicit, в противном случае это ошибка компилятора. Конструктор преобразования фактически не explicit для std::string s, поэтому приведенное выше компилируется.
Вот как обычно инициализируется std::string. Когда s выходит за пределы области видимости, объект s будет уничтожен вместе с базовым буфером строк. Обратите внимание, что следующее имеет тот же эффект (и является другим типичным способом std::string), в том смысле, что он также создает объект с именем s, содержащий "foo" .
std::string s("foo");
Однако существует тонкая разница между std::string s = "foo"; и std::string s("foo");, одна из которых заключается в том, что конструктор преобразования может быть либо explicit, либо не explicit в приведенном выше случае.
std::string s = std::string("foo");
Это называется инициализацией копирования. Это функционально то же самое, что и прямая инициализация
std::string s( "foo" );
но первый требует, чтобы конструктор копирования был доступен, а компиляторы могли создать временный объект, но большинство из них вернутся к временной и прямой конструкции s, содержащей "foo".
std::string s = new std::string("foo");
Это не скомпилируется, потому что new возвращает указатель. Чтобы он работал, вам нужен тип s как std::string *. Затем строка динамически выделяет объект std::string и сохраняет указатель в s. Вам понадобится delete, как только вы закончите использовать его.
std::string s = "foo";
Это почти то же самое, что и первое. Это инициализация копирования, но она имеет дополнительное ограничение. Для этого требуется, чтобы класс std::string содержал конструктор не explicit, который принимает const char *. Это позволяет компилятору неявно построить временный объект std::string. После этого семантика идентична случаю 1.
snew std::string("foo") возвращает указатель на некоторую вновь выделенную память.
Чтобы это сработало, вы должны объявить s как указатель на строку std::string* s.Вы должны использовать третий вариант в большинстве случаев, если не во всех случаях.
1 создаст временную переменную (правую сторону), затем вызовет оператор присваивания, чтобы присвоить значение s
2 создаст экземпляр std::string в куче и вернет указатель на него и не удастся выполнить назначение, потому что вы не можете назначить указатель на не указательный тип
3 построит std::string и инициализирует его с помощью const char*
В номере 1 вы создаете временную строку, используя конструктор, а затем присваиваете ее s. Номер 2 даже не компилируется. На номер 3 вы создаете новую строку, а затем присваиваете ей значение.