Inicializando uma matriz de membros no inicializador do construtor
-
27-09-2019 - |
Pergunta
class C
{
public:
C() : arr({1,2,3}) //doesn't compile
{}
/*
C() : arr{1,2,3} //doesn't compile either
{}
*/
private:
int arr[3];
};
Eu acredito que o motivo é que as matrizes só podem ser inicializadas com =
Sintaxe, isto é:
int arr[3] = {1,3,4};
Perguntas
- Como posso fazer o que quero fazer (isto é, inicializar uma matriz em um construtor (não atribuindo elementos no corpo)). Isso é possível?
- O padrão C ++ 03 diz algo especial sobre a inicialização de agregados (incluindo matrizes) nos inicializadores do CTOR? Ou a invalidância do código acima é um corolário de algumas outras regras?
- As listas de inicializador C ++ 0x resolvem o problema?
Ps Por favor, não mencione os vetores, o impulso :: Matrizes e sua superioridade às matrizes, das quais estou bem ciente.
Solução
- Como posso fazer o que quero fazer (isto é, inicialize uma matriz em um construtor (não atribuindo elementos no corpo)). Isso é possível?
Sim. Está usando uma estrutura que contém uma matriz. Você diz que já sabe disso, mas não entendo a pergunta. Dessa forma, você Faz Inicialize uma matriz no construtor, sem atribuições no corpo. Isso é o que boost::array
faz.
O padrão C ++ 03 diz algo especial sobre a inicialização de agregados (incluindo matrizes) nos inicializadores do CTOR? Ou a invalidância do código acima é um corolário de algumas outras regras?
Um MEM-Inializer usa inicialização direta. E as regras da cláusula 8 proíbem esse tipo de coisa. Não tenho exatamente certeza do caso a seguir, mas alguns compiladores permitem.
struct A {
char foo[6];
A():foo("hello") { } /* valid? */
};
Ver Este GCC Pr para mais detalhes.
As listas de inicializador C ++ 0x resolvem o problema?
Sim, eles fazem. No entanto, sua sintaxe é inválida, eu acho. Você tem que usar aparelhos diretamente para disparar a inicialização da lista
struct A {
int foo[3];
A():foo{1, 2, 3} { }
A():foo({1, 2, 3}) { } /* invalid */
};
Outras dicas
O C ++ 98 não fornece uma sintaxe direta para nada além de zero (ou para elementos que não são do POD, inicializando o valor) a matriz. Para isso, você acabou de escrever C(): arr() {}
.
I Thing Roger Pate está errado sobre as supostas limitações da inicialização agregada de C ++ 0x, mas estou com preguiça de procurar ou conferir, e isso não importa, não é? EDITAR: Roger estava falando sobre "C ++ 03", eu o interpretei como "C ++ 0x". Desculpe, Roger. ☺
Uma solução alternativa C ++ 98 para o seu código atual é embrulhar a matriz em um struct
e inicialize -o de uma constante estática desse tipo. Os dados precisam residir em algum lugar de qualquer maneira. Fora do manguito, pode ficar assim:
class C
{
public:
C() : arr( arrData ) {}
private:
struct Arr{ int elem[3]; };
Arr arr;
static Arr const arrData;
};
C::Arr const C::arrData = {{1, 2, 3}};
Gambiarra:
template<class T, size_t N>
struct simple_array { // like std::array in C++0x
T arr[N];
};
class C : private simple_array<int, 3>
{
static simple_array<int, 3> myarr() {
simple_array<int, 3> arr = {1,2,3};
return arr;
}
public:
C() : simple_array<int, 3>(myarr()) {}
};
- Infelizmente não.
- Você simplesmente não pode da maneira que deseja, pois não é permitido pela gramática (mais abaixo). Você só pode usar a inicialização do tipo CTOR e, como sabe, isso não está disponível para inicializar cada item nas matrizes.
- Acredito que sim, à medida que generalizam a inicialização de várias maneiras úteis. Mas não tenho certeza sobre os detalhes.
Em C ++ 03, a inicialização agregada se aplica apenas à sintaxe semelhante à abaixo, que deve ser uma instrução separada e não se encaixa no inicializador do CTOR.
T var = {...};
Que tal
...
C() : arr{ {1,2,3} }
{}
...
?
Compila Fine em G ++ 4.8
Você quer iniciar uma variedade de INTs em seu construtor? Aponte para uma matriz estática.
class C
{
public:
int *cArray;
};
C::C {
static int c_init[]{1,2,3};
cArray = c_init;
}