Вопрос

Работает ли неизменяемость строк с помощью оператора или со строками внутри оператора?

Например, я понимаю, что следующий код выделит две строки в куче.

string s = "hello ";
s += "world!";

"привет" останется в куче до тех пор, пока не будет собран мусор;и s теперь ссылается на "hello world!" в куче.Однако, сколько строк выделяет следующая строка в куче ... 1 или 2?Кроме того, есть ли инструмент / способ для проверки результатов?

string s = "goodbye " + "cruel world!";
Это было полезно?

Решение

Компилятор имеет специальную обработку для конкатенации строк, именно поэтому второй пример используется только один строка.А "интернирование" означает, что даже если вы запустите эту строку 20000 раз, все равно останется только 1 строка.

Повторное тестирование результатов...самый простой способ (в данном случае), вероятно, это посмотреть в reflector:

.method private hidebysig static void Main() cil managed
{
    .entrypoint
    .maxstack 1
    .locals init (
        [0] string s)
    L_0000: ldstr "goodbye cruel world!"
    L_0005: stloc.0 
    L_0006: ldloc.0 
    L_0007: call void [mscorlib]System.Console::WriteLine(string)
    L_000c: ret 
}

Как вы можете видеть (ldstr), компилятор уже сделал это за вас.

Другие советы

Литеральные строки - это интернированный это означает , что "hello " делает не находиться в куче, но в сегменте данных [см. комментарий] программы (и, следовательно, не имеет права на сборку мусора), то же самое касается "world", что касается "hello world" это также может быть интернировано, если компилятор достаточно умен.

"goodbye cruel world" будет быть интернированным, поскольку конкатенация строковых литералов - это то, что обрабатывается компилятором.


Редактировать: Я не уверен насчет заявления о сегменте данных, пожалуйста, смотрите этот вопрос для получения дополнительной информации.

На самом деле, вероятно, 3.постоянная строка для "goodbye", постоянная строка для "cruel world", а затем новая строка для результата.

Вы можете узнать наверняка, взглянув на сгенерированный код.Это зависит от компилятора (и, на самом деле, от языка, это не очевидно), но вы можете прочитать выходные данные g ++, используя флаг -a (я думаю, проверьте справочную страницу), чтобы получить промежуточный код.

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

string s = "goodbye " + "cruel world!";

В java выделялась бы одна строка.Java использует несколько довольно милых трюков, и ее будет трудно перехитрить - просто никогда не оптимизируйте, пока вам это не понадобится!

Однако в настоящее время, насколько я знаю, используя этот:

String s="";
for(int i=0;i<1000;i++)
    s+=" ";

создание строки из 1000 пробелов по-прежнему, как правило, крайне неэффективно

Добавление в цикле довольно плохо, но в остальном оно, вероятно, так же эффективно, как StringBuilder .

Будьте осторожны здесь, потому что компилятор может выполнить несколько совершенно разных оптимизаций, когда строковые значения известны во время компиляции.Если строки, которые вы используете, неизвестны до выполнения (извлечены из файла конфигурации, базы данных или пользовательского ввода), вы увидите несколько совсем других IL.

Если вы просто собираетесь выполнить одну или две конкатенации строк, я бы не стал беспокоиться об этом.

Однако, если у вас много конкатенаций или у вас есть цикл, то вы определенно хотите принять меры предосторожности.В мире Java это означает, что вы используете StringBuffer вместо объединяющей строки.

Если это не только в одной строке, объединение двух строк может быть выполнено путем преобразования первой строки в StringBuffer, выполнения объединения и возврата результирующей строки.

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

Ни в коем случае не оптимизируйте преждевременно, но и не сбрасывайте со счетов то, насколько неэффективными могут быть конкатонации строк.Дело не в создании объекта, а в работе GC, которую это вызывает.

Есть лаборатория на (ASP.NET Инженер по эскалации) Тесс Фернандес блог, который показывает (довольно экстремальный, конечно) пример как конкатонация строк может поставить сервер на колени.

Если компилятор "умный", то это будет только одна строка с надписью "прощай, жестокий мир!".

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top