строки в C++

Убрать пробел после count

count(distinct patient_id)
     ^----------here
8
задан Quassnoi 10 February 2009 в 20:20
поделиться

9 ответов

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

string a;
a = "hello!";

Сначала Вы инициализируете для содержания пустой строки. (длина набора к 0, и одна или две других операции). Затем Вы присваиваете новое значение, перезаписывая значение длины, которое было уже установлено. Этому, вероятно, также придется выполнить проверку, чтобы видеть, насколько большой текущий буфер, и должно ли больше памяти быть выделено.

string *a;
a = new string("hello!");
...
delete(a);

Новый вызов требует, чтобы ОС и средство выделения памяти нашли свободный блок памяти. Это медленно. Затем Вы сразу инициализируете его, таким образом, Вы ничего не присваиваете дважды или требуете, чтобы буфер, который будет изменен, как Вы, сделали в первой версии. Затем что-то плохо происходит, и Вы забываете звонить, удаляют, и у Вас есть утечка памяти, в дополнение к строке, которая чрезвычайно не спешит выделять. Таким образом, это плохо.

string a;
a = "less"; 
a = "moreeeeeee";

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

Обычно, Вы выделили бы его как это:

string a = "hello";

Одна строка, выполните инициализацию однажды, а не первая инициализация значения по умолчанию и затем присвоение значения, которое Вы хотите.

Это также минимизирует ошибки, потому что у Вас нет бессмысленной пустой строки нигде в Вашей программе. Если строка существует, она содержит значение, которое Вы хотите.

Об управлении памятью, google RAII. Короче говоря, строковые вызовы, новые/удаляющие внутренне для изменения размеров ее буфера. Это означает, что Вы никогда не должны выделять строку с новым. Строковый объект имеет фиксированный размер и разработан, чтобы быть выделенным на стеке, так, чтобы деструктор автоматически назвали, когда он выходит из объема. Деструктор затем гарантирует, что любая выделенная память освобождена. Тем путем Вы не должны использовать новый/удаляющий в Вашем пользовательском коде, что означает, что Вы не пропустите память.

8
ответ дан 5 December 2019 в 05:57
поделиться

Это почти никогда не необходимо или желательно сказать

string * s = new string("hello");

В конце концов, Вы (почти) никогда не говорили бы:

int * i = new int(42);

Необходимо вместо этого сказать

string s( "hello" );

или

string s = "hello";

И да, строки C++ изменяемы.

14
ответ дан 5 December 2019 в 05:57
поделиться
string a;
a = "hello!";

2 операции: называет конструктора по умолчанию std:string () и затем называет оператор:: =

string *a; a = new string("hello!"); ... delete(a);

только одна операция: вызывает конструктора std:string (символ константы*), но Вы не должны забывать выпускать свой указатель.

Что относительно строки ("привет");

2
ответ дан 5 December 2019 в 05:57
поделиться

Существует ли определенная причина, почему Вы постоянно используете присвоение вместо инициализации? Таким образом, почему Вы не пишете

string a = "Hello";

и т.д.? Это избегает конструкции по умолчанию и просто имеет больше смысла семантически. Создание указателя на строку только ради выделения его на "куче" никогда не значимо, т.е. Ваш случай 2 не имеет смысла и немного менее эффективен.

Относительно Вашего последнего вопроса, да, строки в C++ изменяемы, если не объявлено const.

4
ответ дан 5 December 2019 в 05:57
поделиться

В случае, если 1.1, Ваши строковые участники (которые включают указатель на данные) сдержаны stack и память, занятая экземпляром класса, освобождена когда a выходит из объема.

В случае, если 1.2, память для участников выделяется динамично от "кучи" также.

Когда Вы присваиваете a char* постоянный к строке, память, которая будет содержать данные, будет realloc'редактор для установки новым данным.

Можно видеть, сколько памяти выделяется путем вызова string::capacity().

Когда Вы звоните string a("hello"), память выделяется в конструкторе.

И конструктор и оператор присваивания называют те же методы внутренне к выделенной памяти и копируют новые данные там.

0
ответ дан 5 December 2019 в 05:57
поделиться

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

Сам std:string имеет буфер в "куче", которая может быть совместно использована несколькими строками в зависимости от реализации.

Для intsance с реализацией STL Microsoft Вы могли сделать это:

string a = "Hello!";
string b = a;

И обе строки совместно использовали бы тот же буфер, пока Вы не изменили его:

a = "Something else!";

Вот почему это было очень плохо для хранения c_str () для последнего использования; c_str () гарантируют только законность, пока другой вызов к тому строковому объекту не будет выполнен.

Этот вывод к очень противным ошибкам параллелизма, которые потребовали, чтобы эта функциональность совместного использования была выключена с определением при использовании их в многопоточном приложении

0
ответ дан 5 December 2019 в 05:57
поделиться

Если Вы смотрите на документы для строкового класса STL (я полагаю, что документы SGI совместимы к спецификации), многие методы перечисляют гарантии сложности. Я полагаю, что многие гарантии сложности намеренно оставляют неопределенными для разрешения различных реализаций. Я думаю, что некоторые реализации на самом деле используют подход copy-modify, таким образом, что присвоение одной строки другому является постоянно-разовой операцией, но можно понести неожиданные расходы, когда Вы пытаетесь изменить один из тех экземпляров. Не уверенный, если это все еще верно в современном STL все же.

Необходимо также проверить capacity() функция, которая скажет Вам максимальную строку длины, которую можно поместить в приведенный строковый пример, прежде чем это будет вынуждено перераспределить память. Можно также использовать reserve() вызвать перераспределение к определенной сумме, если Вы знаете, что собираетесь быть хранением большой строки в переменной в более позднее время.

Как другие сказали, насколько Ваши примеры идут, необходимо действительно одобрить инициализацию по другим подходам для предотвращения создания временных объектов.

0
ответ дан 5 December 2019 в 05:57
поделиться

Скорее всего,

   string a("hello!");

быстрее, чем что-либо еще.

0
ответ дан 5 December 2019 в 05:57
поделиться

Вы происходите из Java, правильно? В C++ объекты рассматривают то же (большинством способов) как основные типы значения. Объекты могут жить на стеке или в статическом устройстве хранения данных и быть переданы значением. Когда Вы объявляете строку в функции, которая выделяет на стеке однако много байтов, строковый объект берет. Сам строковый объект использует динамическую память для хранения фактических символов, но это очевидно для Вас. Другая вещь помнить состоит в том, что то, когда функциональные выходы и строка Вы объявили, больше не находится в объеме, вся память, которую это использовало, освобождена. Никакая потребность в сборке "мусора" (RAII является Вашим лучшим другом).

В Вашем примере:

string a;
a = "less"; 
a = "moreeeeeee";

Это помещает блок памяти на стеке и называет это a, затем конструктора вызывают и инициализированного к пустой строке. Компилятор хранит байты для "меньше" и "moreeeeeee" в (я думаю), .rdata раздел Вашего exe. Строка желание имеет несколько полей, как поле длины и символ* (я упрощаю значительно). Когда Вы присваиваетесь "меньше" к a, оператор = (), метод называют. Это динамично выделяет память для хранения входного значения, затем копирует его в. При позже присвоении "moreeeeeee" a, оператор = (), метод снова называют, и он перераспределяет достаточно памяти для содержания нового значения при необходимости, затем копирует его в во внутренний буфер.

То, когда строковый объем a's выходит, строковый деструктор называют и память, которая была динамично выделена для содержания фактических символов, освобождено. Затем указатель вершины стека постепенно уменьшается и память, которая не содержала больше "на" стеке.

0
ответ дан 5 December 2019 в 05:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: