Aloque a memória do objeto estaticamente; inicializar dinamicamente?


9

Eu tenho um objeto cujo construtor é passado um parâmetro. Se eu souber o valor do parâmetro em tempo de compilação, posso construir o objeto estaticamente:

static FOOOBJ foo(3);

(Entendo que não é realmente feito estaticamente, ou seja, pelo compilador, mas na verdade é feito durante a instalação).

Mas se eu não souber o valor do parâmetro no tempo de compilação, ainda gostaria de pré-alocar espaço para o objeto, mas construí-lo nesse espaço no tempo de execução. Isso pode ser feito sem um .initialize()método separado ?

Respostas:


3

O uso de um initialize()método para uma classe é contrário ao princípio de um construtor de classe, ou seja, uma vez que uma instância de classe tenha sido construída , ela deve estar " pronta para uso ".

Conforme sugerido pela resposta de Ignacio, a sintaxe de posicionamento do C ++ é muito melhor para o seu propósito.

No entanto, nas bibliotecas do Arduino, a sintaxe de posicionamento não é suportada "pronta para uso", portanto você deve implementá-lo; não tema, isso é bem direto:

void* operator new(size_t size, void* ptr)
{
    return ptr;
}

A sintaxe da veiculação pode ser uma besta complexa em C ++, mas para seu objetivo específico, seu uso pode ser bastante simples:

static char buffer[sizeof FOOOBJ];
static FOOOBJ* foo;

void setup() {
    ...
    foo = new (buffer) FOOOBJ(3);
    ...
}

A diferença com seu código atual é que fooagora é um ponteiro; portanto, qualquer chamada de método será usada em ->vez de ..

Se você quiser continuar usando foocomo instância e não como ponteiro, poderá fazê-lo (mas não o aconselho como explicado mais adiante) usando uma referência :

static char buffer[sizeof FOOOBJ];
static FOOOBJ& foo = *((FOOOBJ*) buffer);

void setup() {
    ...
    new (buffer) FOOOBJ(3);
    ...
}

O problema com esse código é que você não pode saber se foojá foi construído com uma FOOOBJinstância real ou não; usando um ponteiro, você sempre pode verificar se é 0ou não.

Usando a sintaxe do canal, você deve estar ciente de que não pode deletea fooinstância acima. Se você deseja destruir foo(ou seja, garantir que seu destruidor seja chamado), é necessário chamar explicitamente o destruidor:

foo->~FOOOBJ();

11
Eu não estava ciente da sintaxe, mas isso faz total sentido! O construtor precisa estar ciente / projetado para isso? FOOOBJé um objeto do OneWire, usando a biblioteca de Jim Studt (v2.2). Estou recebendo a mensagem error: no matching function for call to 'operator new(unsigned int, byte [14])'na newligação. Parece que o avr-g ++ pode não entender a sintaxe.
JRobert 14/05

Sim, você está certo, estou usando o Eclipse para meus projetos do Arduino e o que eu verifiquei, parecia funcionar, exceto que o que funcionou foi a compilação do Eclipse C ++, não o avr-g ++! Eu editei minha resposta para mostrar uma solução alternativa simples.
Jfpoilpret

Em relação à sua pergunta sobre o construtor, não há um requisito específico, mas se o próprio construtor executar alocação dinâmica, o posicionamento new não o impedirá.
Jfpoilpret

Também estou usando o Eclipse - com qual compilador C ++ é seu configurado? Além disso, olhando para o construtor OneWire, ele não faz newnada, apenas inicializa algumas E / S.
JRobert 14/05

Estou usando o Eclipse com o plug-in eclipse.baeyens.it (que usa ferramentas IDE do Arduino, por exemplo, libs avr-g ++ + Arduino); mas a compilação do C ++ ocorre em tempo real com o Eclipse C ++ e usa o avr-g ++ somente ao iniciar a construção do Arduino. Eu não tinha verificado o último passo inicialmente.
Jfpoilpret

4

Você pode usar a sintaxe do canal para especificar uma alocação existente na qual instanciar a classe.

FOOOBJ foo(0);

 ...

  FOOOBJ *f = new (foo) FOOOBJ(3);

Eu sugiro substituir a declaração de foocom char foo[sizeof FOOOBJ];para que o FOOOBJconstrutor não seja chamado, o fooque poderia ser um problema real, dependendo do que o construtor faz.
Jfpoilpret
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.