Подтвердить что ты не робот

Каков наилучший способ инициализации объекта NSMutableString?

Если я задам следующий вопрос. Каков наилучший способ инициализации класса NSMutableString? (Все экземпляры будут возвращены в неожиданные моменты времени... поэтому я предполагаю, что инициализация выглядит следующим образом:)

  • Если я заранее знаю объем работы. (ожидается)

    NSMutableString *str1 = [NSMutableString stringWithString:@""];
    NSMutableString *str2 = [NSMutableString stringWithCapacity:0];
    NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
    NSMutableString *str4 = [NSMutableString string];
    
    for(int i = 0; i< 1000; i++)
    {
        //The following tasks.(Adding to the string to continue working.)
        [/*str1~str4*/ appendFormat:@"%d", i];
    }
    
  • Если я заранее не знаю объем работы. (неожиданно)

    NSMutableString *str1 = [NSMutableString stringWithString:@""];
    NSMutableString *str2 = [NSMutableString stringWithCapacity:0];
    NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];
    NSMutableString *str4 = [NSMutableString string];
    
    for(int i = 0; i< /*a large of size(unpredictable)*/ ; i++)
    {
        //The following tasks.(Adding to the string to continue working.)
        [/*str1~str4*/ appendFormat:@"%d", i];
    }
    

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

Иногда я иногда работаю с этой задачей.

4b9b3361

Ответ 1

Случай 1

Из перечисленных опций я бы использовал:

NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];

... если вы знаете размер адресата или оцениваете его с небольшой комнатой наверху и можете быстро определить точный размер или сценарий наихудшего случая размера, это может спасти несколько операций перераспределения и копирования. Если вы не знаете размер в худшем случае, или если для вычисления требуется много времени, вы также можете использовать [NSMutableString string] или [NSMutableString new]. Кроме того, *WithCapacity - это подсказка, которую фреймворки могут игнорировать.

Конечно, тело вашего цикла и размер, который вы резервируете, также подразумевают, что все значения [0... 9] (в частности, что все значения потребляют один символ), и вы могли бы в этом случае сделать гораздо лучше используя строки формата с большим количеством аргументов. Однако i, очевидно, больше 9 для большинства итераций и будет потреблять в среднем по 3 символа, поэтому 3000 будет более подходящей резервной емкостью для точного кода, который вы разместили.

Случай 2

Из перечисленных опций я бы использовал:

NSMutableString *str4 = [NSMutableString string];

Еще лучше, если вам не нужно добавлять его в пул автозапуска: [NSMutableString new] или [[NSMutableString alloc] init].

Другие заметки

Да, хранение объектов из пулов автозапуска (например, использование alloc + init) может повысить производительность и значительно сократить пиковое использование памяти. Иногда это не поддается контролю, и в некоторых средах (например, ARC) это может произойти, даже если вы используете конструктор удобных автоуровней - например, [NSMutableString string].

Более быстрое решение

Наконец, если этот случай, который вы наметили, действительно относится к производительности, самым быстрым способом было бы создать буфер char в стеке, а затем создать один NSString из результата копирования чисел на char. Предполагая, что ваш int - все 0-9, это будет очень быстро и просто, а затем просто создайте NSString из (завершенной) cstring. Вы даже можете сделать это, если размер ввода варьируется или очень большой (приводит к очень длинной строке).

Ответ 2

Это не имеет значения.

Если вы оптимизировали свою программу до сих пор, что это решение окажет заметное влияние на ее общую производительность, похлопайте себя по спине или, как сказал бы Шелдон из BBT, "сделайте шоколад!"

PS:
Если вы точно знаете размер спереди или имеете действительно хорошую оценку на нем, используйте этот размер в stringWithCapacity: или initWithCapacity:, если вы этого не сделаете, тогда даже не беспокойтесь - пусть решает вопрос, он довольно проклятый умный!

Ответ 3

Вот кратчайший путь:

NSMutableString *string = [@"" mutableCopy];

Ответ 4

Если вы знаете размер аванса, используйте

 [NSMutableString stringWithCapacity: _Known_Size_];

Если вы не знаете размер спереди, используйте

 [NSMutableString stringWithCapacity: _small_number_];

Затем измененная строка будет расти, как это необходимо.

Ответ 5

NSMutableString *str1 = [NSMutableString stringWithString:@""];

Плохо, NSString (@"") бессмысленно создается, а затем копируется в новую строку NSMutable String

NSMutableString *str2 = [NSMutableString stringWithCapacity:0];

Плохо, NSMutableString с емкостью 0 необходимо будет надуть при первом добавлении к ней.

NSMutableString *str3 = [NSMutableString stringWithCapacity:1000];

Хорошо, если 1000 имеет некоторое значение (т.е. это ожидаемый размер для контента, с которым вы работаете).

NSMutableString *str4 = [NSMutableString string];

Хорошо, используя метод удобства, который похож на выполнение [NSMutableString alloc] init];

Ответ 6

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

Итак,

NSMutableString* stringOne = [[NSMutableString alloc] initWithCapacity:capacity];

вместо

NSMutableString* stringTwo = [NSMutableString stringWithCapacity:capacity];

Просто помните, что вам нужно освободить stringOne, когда вы закончите с ним, но не stringTwo, потому что метод stringWithCapacity: class возвращает объект с автореализацией.

Подробнее читайте здесь: http://www.mulle-kybernetik.com/artikel/Optimization/opti-5.html