Pergunta

O meu entendimento é que ambos criar um NSMutableString, apenas o primeiro é de propriedade do sistema e o segundo é possuído por mim (ou seja, eu preciso liberá-lo). Existe alguma razão específica para que eu deveria usar um ou o outro, em face do que parece mais fácil de usar o primeiro? Também é o primeiro melhor, pois dá o compilador uma sensação de tamanho?

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

ou

NSMutableString *newPath = [[NSMutableString alloc] init];

EDIT ... TAMBÉM

Eu vejo um monte de declarações escritas em duas linhas (ou seja.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

Pessoalmente eu prefiro o one-liner, este é apenas mais um exemplo de estilo pessoal?

Foi útil?

Solução

NSMutableString *newPath = [NSMutableString stringWithCapacity:42];

ou

NSMutableString *newPath = [[NSMutableString alloc] init];

Existe alguma razão específica para que eu deveria usar um ou o outro, em face do que parece mais fácil de usar o primeiro?

Sim. Sempre autorelease imediatamente, a menos que você tenha um motivo específico para não.

A primeira razão é que é muito fácil de se esqueça de escrever a mensagem release. Se você autorelease o objeto na mesma declaração onde você criá-lo (como na [[[… alloc] init] autorelease]), é muito mais difícil de esquecer isso e muito mais evidente quando você faz. Os métodos de conveniência de fábrica (como stringWithCapacity:) autorelease o objeto para você, assim como quando você autorelease-lo sozinho, você não precisa se preocupar em liberá-lo mais tarde.

Em segundo lugar, mesmo se você não se esqueça de escrever a mensagem release separado, é fácil não atingi-lo. Duas maneiras são os primeiros retornos:

NSString *str = [[NSString alloc] initWithString:@"foo"];

BOOL success = [str writeToFile:path atomically:NO];
if (!success)
    return;

[str release];

e exceções lançadas ou propagadas:

NSString *str = [[NSString alloc] initWithString:@"foo"];

//Throws NSRangeException if str is not in the array or is only in the array as the last object
NSString *otherStr = [myArray objectAtIndex:[myArray indexOfObject:str] + 1];

[str release];

O “motivo específico para não” é geralmente que você tem um loop que cria um monte de objetos, caso em que você pode querer gerir manualmente como muitos dos objetos no loop como você pode, a fim de manter seu objeto de contagem regressiva. No entanto, só faça isso se você tiver provas de que este é o seu problema (seja ele números concretos de Shark, números rígidos de Instrumentos, ou o seu sistema indo para paginação inferno sempre que loop é executado tempo suficiente).

Outro, possivelmente mais, soluções incluem a divisão do ciclo em dois circuitos encaixados (o exterior para criar e drenar uma piscina disparo automático para o ciclo interior) e a mudança para NSOperation. (No entanto, certifique-se de definir um limite de quantas operações das filas é executado em um tempo de outra forma, você pode torná-lo ainda mais fácil para entrar em paginação inferno .)

Também é o primeiro melhor, pois dá o compilador uma sensação de tamanho?

É melhor, mas não por esse motivo.

Para o compilador, é apenas uma outra mensagem classe. O compilador não saber ou se importar o que ele faz; para tudo o que sabe e cuidados, stringWithCapacity: é a mensagem para tocar uma música para o usuário.

Ela dá NSMutableString a sugestão de tamanho-classe vai saber o quanto de armazenamento de caracteres que pode querer alocar inicialmente. Seja qual for o benefício que você começa a partir deste é provavelmente pequeno (pelo menos no Mac), mas se você tem a informação útil, por que não usá-lo? Por outro lado, eu não iria sair do meu caminho para calculá-lo.

Eu vejo um monte de declarações escritas em duas linhas (ou seja.)

NSMutableString *newPath;
newPath = [NSMutableString stringWithCapacity:42];

Pessoalmente eu prefiro o one-liner, este é apenas mais um exemplo de estilo pessoal?

Sim. No entanto, há uma certa quantidade de risco em deixar uma variável não inicializada. Definitivamente ativar a configuração construção “Run estática Analyzer” se você decidir fazer um hábito disso.

Outras dicas

O primeiro não é para o compilador necessariamente, mas sim uma sugestão para a cadeia de como ele pode ser capaz de otimizar o armazenamento de seus dados. Esta é mais útil para NSDictionary / NSArray / NSSet, que têm a capacidade de internamente alterar suas implementações, dependendo do tamanho do seu conjunto de dados .

Além disso, você está correto: a única diferença é uma questão de propriedade. Eu quase nunca usar os métodos WithCapacity, e sim apenas usar [NSMutableString string] ou [NSMutableArray array], mas IMO, é realmente apenas uma questão de estilo e você não vai ganhar ou qualquer coisa perder usando um sobre o outro.

O primeiro é uma string autoreleased. Esta será lançado pelo sistema em um ponto apropriado. Ele é adicionado ao pool de disparo automático e memória serão tratadas pelo sistema. Uma vez que está fora do escopo, você não pode garuntee que será válido. Este tipo é útil se ele só tem escopo dentro do seu método, e também para o retorno de valores a partir de métodos.

O segundo é mantido, assim terá uma contagem de referência de 1 e não é adicionado ao pool de disparo automático. Você é responsável por liberá-lo e liberar a memória. Utilize este método se você quiser controlar o escopo do objeto. Usado para variáveis ??de membro etc.

Eu acredito que a inicialização 2 linha é apenas estilo, mas eu não usaria a variação de 2 linhas como você está definindo a variável sem assinging um valor a ela, mesmo que você está na linha seguinte. Eu acho que esse tipo de espelhos membro variável declaração / inicialização, mas eu não pessoalmente gosto muito.

Você levantar questões válidas. Ela realmente depende do que você está fazendo, mas para geral iPhone apps Eu diria que usar apenas o primeiro. Este será limpa automaticamente para você quando a contagem de referência chega a 0 e você não precisa se preocupar com isso.

Use o segundo quando você realmente tem um bom motivo para gerenciar a memória da seqüência de si mesmo. Tal como você quer ter certeza de quando a cadeia deve ser limpo, ou você espera de memória para ser mínima em um determinado momento.

Eu diria como um uso geral regra o segundo quando você tem uma boa razão para fazê-lo.

Você está correto em todos os seus pontos!

Eu não tenho certeza o quão grande a diferença do tamanho / capacidade dica marcas, mas mais informações certamente deve permitir que o tempo de execução a tomar melhores decisões.

Por que usar um estilo sobre o outro? Bem, objetos quando são autoreleased lançado? Há duas razões não-óbvias porque poderia importam. Em primeiro lugar, quando um método usa uma grande quantidade de memória que você pode liberar imediatamente. (Você também pode usar um pool de disparo automático local, eu acho.) Em segundo lugar, acho que o uso de disparo automático pode esconder vazamentos de memória e fazer a depuração algum código mais difícil. Sua milhagem pode variar, dependendo da idade e da qualidade do código.

Quando eu comecei a desenvolver aplicativos do iPhone eu usei autoreleased objetos o tempo todo. Era conveniente porque eu não entender completamente como tudo funcionou e, geralmente, fez a coisa certa. Esses dias eu tendem a errar no lado da memória desalocar manualmente. Realmente não é tão difícil quando você realmente entender como funciona a contagem de referência e as forças a questão imediatamente quando você não.

Se você tem certeza quanto tempo uma corda que você precisa, vá em frente e usar o -initWithCapacity: método. Quando você exceder o armazenamento de uma string, ele é realocado e copiado, que não é uma operação barata.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top