vectores matrices inicializar imprimir funciones con como cargar cadenas arreglos arreglo c++ stl

c++ - inicializar - matrices en c



¿Por qué no se puede usar una declaración directa para un std:: vector? (8)

Si creo una clase así:

// B.h #ifndef _B_H_ #define _B_H_ class B { private: int x; int y; }; #endif // _B_H_

y úsalo así:

// main.cpp #include <iostream> #include <vector> class B; // Forward declaration. class A { public: A() { std::cout << v.size() << std::endl; } private: std::vector<B> v; }; int main() { A a; }

El compilador falla al compilar main.cpp . Ahora la solución que sé es #include "Bh" , pero tengo curiosidad de por qué falla. Ninguno de los mensajes de error de g++ o cl fue muy esclarecedor en este asunto.


El compilador necesita saber cuán grande es "B" antes de poder generar la información de diseño adecuada. Si, en cambio, dijera std::vector<B*> , entonces el compilador no necesitaría saber qué tan grande es B porque sabe qué tan grande es un puntero.


La razón por la que no puede usar una declaración directa es porque el tamaño de B es desconocido.

No hay ninguna razón en tu ejemplo de que no puedas incluir a Bh dentro de Ah, entonces, ¿qué problema estás tratando de resolver realmente?

Editar: También hay otra manera de resolver este problema: ¡deja de usar C / C ++! Es tan 1970s ...;)


Para instanciar A :: v, el compilador necesita saber el tipo concreto de B.

Si intenta minimizar la cantidad de # equipaje incluido para mejorar los tiempos de compilación, hay dos cosas que puede hacer, que en realidad son variaciones entre sí:

  1. Usa un puntero a B
  2. Use un proxy liviano para B

Es más que solo el tamaño de B que se necesita. Los compiladores modernos tendrán trucos sofisticados para acelerar las copias vectoriales utilizando memcpy cuando sea posible, por ejemplo. Esto se logra comúnmente al especializarse parcialmente en la POD-ness del tipo de elemento. No puede decir si B es un POD de una declaración directa.


Esto no importa si usa un vector o simplemente intenta crear una instancia de uno. La instanciación requiere la definición completa de un objeto.


De hecho, su ejemplo se construiría si el constructor de A se implementara en una unidad de compilación que conoce el tipo de B.

Una instancia std :: vector tiene un tamaño fijo, sin importar qué T sea, ya que contiene, como otros dijeron antes, solo un puntero a T. Pero el constructor del vector depende del tipo concreto. Su ejemplo no se compila porque A () intenta llamar al ctor del vector, que no se puede generar sin conocer B. Esto es lo que funcionaría:

Declaración de A:

// A.h #include <vector> class B; // Forward declaration. class A { public: A(); // only declare, don''t implement here private: std::vector<B> v; };

Implementación de A:

// A.cpp #include "A.h" #include "B.h" A::A() // this implicitly calls vector<B>''s constructor { std::cout << v.size() << std::endl; }

Ahora un usuario de A necesita saber solo A, no B:

// main.cpp #include "A.h" int main() { A a; // compiles OK }


Al igual que dijo fyzix, la razón por la que su declaración directa no funciona es debido a su constructor en línea. Incluso un constructor vacío puede contener muchos códigos, como la construcción de miembros que no son POD. En su caso, tiene un vector para inicializar, que no puede hacer sin definir completamente su tipo de plantilla.

Lo mismo vale para los destructores. El vector necesita la definición del tipo de plantilla para indicar a qué destructor llamar cuando destruye las instancias que contiene.

Para deshacerse de este problema, simplemente no constructor y destructores en línea. Defínelos por separado en algún lugar después de que B esté completamente definido.

Para más información, http://www.chromium.org/developers/coding-style/cpp-dos-and-donts


Hombre, estás instalando std::vector con un tipo incompleto. No toque la declaración directa, solo mueva la definición del constructor al archivo .cpp .