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

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

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

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

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

string s = "goodbye " + "cruel world!";
12 голосов | спросил Aaron Daniels 16 TueEurope/Moscow2008-12-16T22:18:42+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:18:42 +0300 2008, 22:18:42

9 ответов


0

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

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

.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), компилятор уже сделал это за вас.

ответил Marc Gravell 16 TueEurope/Moscow2008-12-16T22:22:12+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:22:12 +0300 2008, 22:22:12
0

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

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


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

ответил Motti 16 TueEurope/Moscow2008-12-16T22:26:52+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:26:52 +0300 2008, 22:26:52
0

На самом деле, вероятно 3. константная строка для "до свидания", константная строка для "жестокого мира", а затем новая строка для результата.

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

ответил Charlie Martin 16 TueEurope/Moscow2008-12-16T22:25:15+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:25:15 +0300 2008, 22:25:15
0

Не верьте тому, что вы «знаете» о строках. Вы можете просмотреть исходный код для реализации строки. Например, ваш пример:

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

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

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

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

создание строки из 1000 пробелов все еще имеет тенденцию быть крайне неэффективным

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

ответил Bill K 16 TueEurope/Moscow2008-12-16T22:26:00+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:26:00 +0300 2008, 22:26:00
0

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

ответил Joel Coehoorn 16 TueEurope/Moscow2008-12-16T23:13:40+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 23:13:40 +0300 2008, 23:13:40
0

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

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

ответил Stephane Grenier 16 TueEurope/Moscow2008-12-16T23:29:18+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 23:29:18 +0300 2008, 23:29:18
0

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

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

ответил SeaDrive 16 TueEurope/Moscow2008-12-16T23:44:05+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 23:44:05 +0300 2008, 23:44:05
0

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

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

ответил Richard Szalay 17 WedEurope/Moscow2008-12-17T00:05:48+03:00Europe/Moscow12bEurope/MoscowWed, 17 Dec 2008 00:05:48 +0300 2008, 00:05:48
0

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

ответил Burkhard 16 TueEurope/Moscow2008-12-16T22:22:49+03:00Europe/Moscow12bEurope/MoscowTue, 16 Dec 2008 22:22:49 +0300 2008, 22:22:49

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132