Ответ 1
Да, это зависит от языка, поскольку хранилище строк отличается между языками.
- Строки типа Pascal:
Length = 0
. - Строки в стиле C:
[0] == 0
. - .NET:
.IsNullOrEmpty
.
Etc.
Что более эффективно для компилятора и лучше всего проверяет, является ли строка пустой?
Кроме того, зависит ли ответ от языка?
Да, это зависит от языка, поскольку хранилище строк отличается между языками.
Length = 0
.[0] == 0
..IsNullOrEmpty
.Etc.
В языках, использующих строки C-стиля (с нулевым завершением), по сравнению с ""
будет быстрее. То, что операция O (1), взяв длину строки в стиле C, - O (n).
В языках, которые хранят длину как часть строкового объекта (С#, Java,...), проверка длины также O (1). В этом случае непосредственная проверка длины выполняется быстрее, поскольку она позволяет избежать накладных расходов на создание новой пустой строки.
В .Net:
string.IsNullOrEmpty( nystr );
Строки могут быть нулевыми, поэтому .Length иногда выдает исключение NullReferenceException
В языках, использующих строки C-стиля (с нулевым завершением), по сравнению с "" будет быстрее
На самом деле, может быть, лучше проверить, является ли первый char в строке "\ 0":
char *mystring;
/* do something with the string */
if ((mystring != NULL) && (mystring[0] == '\0')) {
/* the string is empty */
}
В Perl есть третий вариант, что строка undefined. Это немного отличается от указателя NULL в C, хотя бы потому, что вы не получаете ошибку сегментации для доступа к строке undefined.
В Java 1.6 класс String имеет новый метод isEmpty
Существует также библиотека Jakarta commons, которая имеет метод isBlank. Бланк определяется как строка, содержащая только пробелы.
String.IsNullOrEmpty()
работает только на .net 2.0 и выше, для .net 1/1.1, я склонен использовать:
if (inputString == null || inputString == String.Empty)
{
// String is null or empty, do something clever here. Or just expload.
}
Я использую String.Empty в отличие от ", потому что" "создаст объект, тогда как String.Empty wont - я знаю его что-то маленькое и тривиальное, но id еще не создает объекты, когда мне они не нужны! ( Источник)
Предполагая, что ваш вопрос .NET:
Если вы хотите проверить свою строку на недействительность, используйте IsNullOrEmpty, если вы уже знаете, что ваша строка не является нулевой, например, при проверке TextBox.Text и т.д., не используйте IsNullOrEmpty, а затем задайте свой вопрос.
Поэтому, по моему мнению, String.Length меньше производительности, чем сравнение строк.
Я тестировал это событие (я также тестировал С#, тот же результат):
Module Module1
Sub Main()
Dim myString = ""
Dim a, b, c, d As Long
Console.WriteLine("Way 1...")
a = Now.Ticks
For index = 0 To 10000000
Dim isEmpty = myString = ""
Next
b = Now.Ticks
Console.WriteLine("Way 2...")
c = Now.Ticks
For index = 0 To 10000000
Dim isEmpty = myString.Length = 0
Next
d = Now.Ticks
Dim way1 = b - a, way2 = d - c
Console.WriteLine("way 1 took {0} ticks", way1)
Console.WriteLine("way 2 took {0} ticks", way2)
Console.WriteLine("way 1 took {0} ticks more than way 2", way1 - way2)
Console.Read()
End Sub
End Module
Результат:
Way 1...
Way 2...
way 1 took 624001 ticks
way 2 took 468001 ticks
way 1 took 156000 ticks more than way 2
Это означает, что сравнение проходит больше, чем проверка длины строки.
Собственно, IMO - лучший способ определить метод IsNullOrEmpty() класса string.
http://msdn.microsoft.com/en-us/library/system.string.isnullorempty.
Обновление: я предположил, что .Net, на других языках, это может быть другим.
В этом случае прямая проверка длины выполняется быстрее, поскольку она позволяет избежать накладных расходов на создание новой пустой строки.
@DerekPark: Это не всегда так. "" является строковым литералом, поэтому на Java он почти наверняка уже будет интернирован.
Для строк C,
if (s[0] == 0)
будет быстрее, чем
if (strlen(s) == 0)
или
if (strcmp(s, "") == 0)
потому что вы избежите накладных расходов на вызов функции.
@Натан
На самом деле, может быть, лучше проверить, является ли первый char в строке "\ 0":
Я почти упомянул об этом, но в итоге оставил его, так как вызов strcmp()
с пустой строкой и непосредственная проверка первого символа в строке - это O (1). Вы в основном просто платите за дополнительный вызов функции, который довольно дешев. Если вам действительно нужна абсолютная максимальная скорость, определенно перейдите к прямому сравнению с char -to-0.
Честно говоря, я всегда использую strlen() == 0
, потому что я никогда не писал программу, где это была действительно измеримая проблема с производительностью, и я думаю, что наиболее читаемый способ выразить проверку.
Опять же, не зная языка, это невозможно сказать.
Тем не менее, я рекомендую вам выбрать технику, которая имеет наибольший смысл для программиста по обслуживанию, который следует и должен будет поддерживать вашу работу.
Я бы рекомендовал написать функцию, которая явно делает то, что вы хотите, например
#define IS_EMPTY(s) ((s)[0]==0)
или сопоставимы. Теперь нет сомнений в том, что вы проверяете.
После того, как я прочитал эту тему, я провел небольшой эксперимент, который дал два разных и интересных вывода.
Рассмотрим следующее.
strInstallString "1" string
Вышеприведенное копируется из окна локалей отладчика Visual Studio. Это же значение используется во всех трех следующих примерах.
if (strInstallString == "") === if (strInstallString == string.Empty)
Ниже приведен код, отображаемый в окне дизассемблера отладчика Visual Studio 2013 для этих двух принципиально идентичных случаев.
if ( strInstallString == "" )
003126FB mov edx,dword ptr ds:[31B2184h]
00312701 mov ecx,dword ptr [ebp-50h]
00312704 call 59DEC0B0 ; On return, EAX = 0x00000000.
00312709 mov dword ptr [ebp-9Ch],eax
0031270F cmp dword ptr [ebp-9Ch],0
00312716 sete al
00312719 movzx eax,al
0031271C mov dword ptr [ebp-64h],eax
0031271F cmp dword ptr [ebp-64h],0
00312723 jne 00312750
if ( strInstallString == string.Empty )
00452443 mov edx,dword ptr ds:[3282184h]
00452449 mov ecx,dword ptr [ebp-50h]
0045244C call 59DEC0B0 ; On return, EAX = 0x00000000.
00452451 mov dword ptr [ebp-9Ch],eax
00452457 cmp dword ptr [ebp-9Ch],0
0045245E sete al
00452461 movzx eax,al
00452464 mov dword ptr [ebp-64h],eax
00452467 cmp dword ptr [ebp-64h],0
0045246B jne 00452498
if (strInstallString == string.Empty) не сильно отличается
if ( strInstallString.Length == 0 )
003E284B mov ecx,dword ptr [ebp-50h]
003E284E cmp dword ptr [ecx],ecx
003E2850 call 5ACBC87E ; On return, EAX = 0x00000001.
003E2855 mov dword ptr [ebp-9Ch],eax
003E285B cmp dword ptr [ebp-9Ch],0
003E2862 setne al
003E2865 movzx eax,al
003E2868 mov dword ptr [ebp-64h],eax
003E286B cmp dword ptr [ebp-64h],0
003E286F jne 003E289C
Из приведенных выше списков машинного кода, сгенерированных модулем NGEN.NET Framework версии 4.5, я делаю следующие выводы.
Тестирование равенства для пустого литерала строки и статического свойства string.Empty в классе System.string для всех практических целей идентичны. Единственное различие между двумя фрагментами кода - это источник первой команды перемещения, и оба являются смещениями относительно ds, подразумевая, что оба относятся к константам запекания.
Тестирование равенства для пустой строки, как либо литерала, либо свойства string.Empty, устанавливает вызов функции с двумя аргументами, который указывает на неравенство, возвращая нуль. Я основываю этот вывод на других тестах, которые я выполнил пару месяцев назад, в которых я выполнил некоторые из своих собственных кодов через управляемый/неуправляемый разрыв и обратно. Во всех случаях любой вызов, требующий два или более аргументов, помещает первый аргумент в регистр ECX, а второй - в регистр EDX. Я не помню, как были приняты последующие аргументы. Тем не менее, настройка вызова больше напоминала __fastcall, чем __stdcall. Аналогично, ожидаемые возвращаемые значения всегда отображались в регистре EAX, который почти универсален.
Тестирование длины строки задает вызов функции с одним аргументом, который возвращает 1 (в регистре EAX), который является длиной тестируемой строки.
Учитывая, что сразу видимый машинный код почти идентичен, единственная причина, по которой я могу представить, что будет учитывать лучшую производительность равенства строк по длине строки, указанному Shinny, - это что функция с двумя аргументами, которая выполняет сравнение, значительно оптимизирована, чем функция с одним аргументом, которая считывает длину от экземпляра строки.
Заключение
В принципе, я избегаю сравнения с пустой строкой как литералом, потому что пустой литерал строки может выглядеть неоднозначно в исходном коде. С этой целью мои .NET-хелперные классы уже давно задали пустую строку как константу. Хотя я использую string.Empty для прямых, встроенных сравнений, константа зарабатывает свое содержание для определения других констант, значение которых является пустой строкой, потому что константе нельзя назначить string.Empty как его значение.
Это упражнение позволяет раз и навсегда решить любую проблему, связанную со стоимостью, если таковая имеется, для сравнения с string.Empty или константой, определяемой моими вспомогательными классами.
Однако он также вызывает загадочный вопрос, чтобы заменить его; почему сравнение с string.Empty более эффективно, чем тестирование длины строки? Или тест, используемый Синни, недействителен, потому что, кстати, цикл реализован? (Я считаю, что трудно поверить, но, опять же, меня уже обманули, как я уверен, вы тоже!)
Я уже давно предполагал, что объекты system.string считаются строками, в основном похожими на давно установленный Basic String (BSTR), который мы давно знаем из COM.