Crash na windowsie przy przypisywaniu wartości z wektora do tablicy
Ostatnio zmodyfikowano 2017-05-14 17:07
Szustarol Temat założony przez niniejszego użytkownika |
Crash na windowsie przy przypisywaniu wartości z wektora do tablicy » 2017-05-12 08:58:14 Może najpierw kod: main: #include <iostream> #include "Vector2D.h"
int main() { Vector2D < int > test( 0, 0 ); int testarray[ 2 ][ 3 ] = { { 10, 10, 5 }, { 2, 4, 1 } }; for( int i = 0; i < 2; i++ ) { for( int j = 0; j < 3; j++ ) { std::cout << testarray[ i ][ j ] << ", "; } std::cout << std::endl; } test.FromArray(( int * ) testarray, 2, 3 ); int ** ret = test.ToArray(); for( int i = 0; i < test.GetHeight(); i++ ) { for( int j = 0; j < test.GetWidth(); j++ ) { std::cout << ret[ i ][ j ] << ", "; } std::cout << std::endl; } }
vector2d.h: #ifndef VECTOR2D_H #define VECTOR2D_H #include <vector>
template < class T > class Vector2D { public: Vector2D( int width, int height ); ~Vector2D(); T ** ToArray(); void FromArray( T *, int, int ); int GetWidth(); int GetHeight(); protected: private: int Width, Height; bool ArraySet; T ** Array; std::vector < T >* LinearVector; };
#endif
vector2d.cpp: #include "Vector2D.h" #include <iostream>
template < class T > Vector2D < T >::Vector2D( int height, int width ) { this->Width = width; this->Height = height; this->LinearVector = new std::vector < T >; this->LinearVector->resize( width * height ); this->ArraySet = false; }
template < class T > Vector2D < T >::~Vector2D() { delete( this->LinearVector ); if( this->ArraySet ); delete( this->Array ); }
template < class T > T ** Vector2D < T >::ToArray() { if( this->ArraySet ) delete( this->Array ); this->ArraySet = true; this->Array = new T *[ this->Height ]; for( int i = 0; i < this->Height; i++ ) this->Array[ i ] = new T[ this->Width ]; for( int y = 0; y < this->Height; y++ ) for( int x = 0; x < this->Width; x++ ) this->Array[ y ][ x ] = this->LinearVector->at( this->Width * y + x ); return this->Array; }
template < class T > void Vector2D < T >::FromArray( T * arr, int height, int width ) { this->Width = width; this->Height = height; delete( this->LinearVector ); this->LinearVector->resize( width * height ); for( int y = 0; y < height; y++ ) { for( int x = 0; x < width; x++ ) { this->LinearVector->at( y * width + x ) = *( arr + x + y * width ); } } }
template < class T > int Vector2D < T >::GetWidth() { return this->Width; }
template < class T > int Vector2D < T >::GetHeight() { return this->Height; }
template class Vector2D < int >; template class Vector2D < char >; template class Vector2D < std::string >; template class Vector2D < float >; template class Vector2D < double >;
Jak widać próbuję zrobić klasę, która przechowuje logiczną tablicę dwuwymiarową jako pojedynczy wektor w kodzie oznaczyłem miejsce crasha, co ciekawe: this->Array[y][x] = this->LinearVector->at(this->Width*y + x); - oczywiście nie zadziała this->Array[y][x] = 0; - już zadziała std::cout << this->LinearVector->at(this->Width*y + x) << ", "; - także zadziała
więc pozornie wszystko powinno być ok, bo wartości są poprawne po tym jak sprawdzałem tylko nie wiem czemu przypisanie z tego wektora nie działa. Dzięki z góry za pomoc |
|
Monika90 |
» 2017-05-12 09:48:57 W funkcji FromArray jest coś takiego delete( this->LinearVector ); this->LinearVector->resize( width * height );
|
|
darko202 |
» 2017-05-12 10:20:53 1. mnie zastanawia to, że T ** Array; chyba powinno być zainicjalizowane jak np. na https://www.tutorialspoint.com/cplusplus/cpp_pointer_to_pointer.htmint var; int * ptr; int ** pptr;
var = 3000;
ptr = & var;
pptr = & ptr;
w konstruktorze tego nie ma, a w main od razu odwołujesz się do metody test.FromArray(( int * ) testarray, 2, 3 ); a w niej nie ma inicjalizacji dlatego Array[ y ][ x ] jest odwołaniem się do pustki 2. mógłbyś dołożyć komunikat błędu jaki otrzymujesz bo dziś znów jestem zbyt leniwy, aby odtwarzać Twój błąd Sorry 3. poznaj technikę debugowania kodu - sporo ułatwia uruchamiam program -> zatrzymuję się przed linia błędu -> oglądam stan zmiennych i bardzo często błąd jest szybko namierzany (choć czasem po n tym podejściu) Powodzenia :) |
|
Szustarol Temat założony przez niniejszego użytkownika |
» 2017-05-12 15:37:18 dzięki Monika, faktycznie nie zauważyłem tego delete( this->LinearVector );
to teraz jeszcze jedno pytanko macie jakiś pomysł jak zmienić funkcję fromarray, aby nie trzeba było castować, np. jak do (int*) na powyższym przykładzie? |
|
Monika90 |
» 2017-05-12 16:30:09 Spróbuj z szablonem template < class T > class Vector2 { public: template < class U, std::size_t width, std::size_t height > void from_array( const U( & array )[ height ][ width ] ) { } };
|
|
Szustarol Temat założony przez niniejszego użytkownika |
» 2017-05-14 14:57:11 czy taki szablon wymaga definiowania ciała funkcji w pliku nagłówkowym? jak się do niego odnieść w .cpp? Poza tym, jeśli chcę aby szablon był "dynamiczny" a nie tylko dla typów które określam na dole pliku .cpp, to muszę ciała funkcji definiować w pliku .h? |
|
Monika90 |
» 2017-05-14 17:07:26 Poza tym, jeśli chcę aby szablon był "dynamiczny" a nie tylko dla typów które określam na dole pliku .cpp, to muszę ciała funkcji definiować w pliku .h?
|
Tak. No chyba że używasz go tylko w jednym pliku cpp, to wtedy definicja może być tylko w tym pliku. template < class U, std::size_t width, std::size_t height > void from_array( const U( & array )[ height ][ width ] ) { }
Parametrami tego szablonu są wymiary tablicy, więc musiałbyś dokonać jawnego konkretyzowania dla wszystkich możliwych wymiarów które chcesz użyć, co jest niepraktyczne, więc jego definicja musi być w pliku nagłówkowym. I jeszcze jedno, class U jest tam po to żeby można było wywołać from_array z argumentem kompatybilnego typu, np. Vector2D < int > v; float a[ 5 ][ 7 ] = { }; v.from_array( a );
Jeżeli chcesz bardziej ścisłego dopasowania, to usuń class U, a U zastąp przez T template < class T > class Vector2d { public: template < std::size_t width, std::size_t height > void from_array( const T( & array )[ height ][ width ] ) { } };
|
|
« 1 » |