对象指针 c++ 的全局向量错误



我正在用 c++ 开发一个 2D 物理引擎,我使用的主要结构之一是名称 RigidBody。为了在每个时间步中轻松遍历所有 RigidBody 对象,我尝试创建 RigidBody 对象指针的全局向量。

vector<RigidBody*> RigidBodies

正如其他 StackOverflow 答案中所建议的那样,我在头文件中声明了全局变量,并在另一个项目.cpp文件中定义了它。但是,当我尝试访问成员函数或变量时,我得到的是虚假值。下面是我的源文件和头文件。有人可以让我知道这是否有错误,或者我是否做了一些根本性错误的事情,因为我几天来一直在尝试查找错误,但尚未弄清楚。

主.cpp:

#include <iostream>
#include <vector>
#include "polygon.h"
#include "rendering.h"
int test;
std::vector<RigidBody*> RigidBodies;
RigidBody * rigPtr;
void CreateBody() {
Material m1;  // Settings for ROCK.
m1.density = 0.6;
m1.restitution = 0.1;
float volume = 1;
Vector p0 = {0,1};
Vector p1 = {1,1};
Vector p2 = {1,0};
Vector p3 = {0,0};
std::vector<Vector*> Points;
Points.push_back(&p0);
Points.push_back(&p1);
Points.push_back(&p2);
Points.push_back(&p3);
//std::cout << Points.at(0)->y << 'n';
Polygon pol1(Points, m1, volume);
Polygon * polPtr  = &pol1; 
//std::cout << pol1.Points.at(0)->y << 'n';
std::cout << "polygon created" << 'n';
Vector pos1;
pos1.x = 10;
pos1.y = 10;
RigidBody r1(pos1, polPtr);
rigPtr = &r1;
std::cout << "rigid body created" << 'n';
// std::cout << RigidBodies.at(0)->dt << 'n';
}
// MAIN
int main() {
test = 3;
//std::cout << test << 'n';
test = 6;
CreateBody();
RigidBodies.push_back(rigPtr);
//std::cout << test << 'n';
unsigned int lastTime = SDL_GetTicks();
unsigned int currentTime;
SDL_Renderer* renderer = InitializeRender();
while(1) {
currentTime = SDL_GetTicks();
if (currentTime - lastTime > 33) {
//RigidBodies.at(0)->Step();
Render(renderer, RigidBodies);
lastTime = SDL_GetTicks();
}
}
return(0);
}

渲染.cpp:

#include <iostream>
#include "polygon.h"
#include "rendering.h"

SDL_Renderer* InitializeRender() {
SDL_Window * window = NULL;
window = SDL_CreateWindow
(
"RIGID BODIES SIM", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
640,
480,
SDL_WINDOW_SHOWN
);
// Setup renderer
SDL_Renderer * renderer = NULL;
renderer =  SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
return(renderer);
}
void Render(SDL_Renderer * renderer, std::vector<RigidBody*> RigidBodies) {
float scale = 10;  // METERS to PIXELS.
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);  // Clear screen.
SDL_RenderClear(renderer);
SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);  // Set polygon drawing color (GREEN)
std::cout << RigidBodies.at(0)->dt << 'n';
for (int j = 0; j < RigidBodies.size(); j++) {
RigidBody * rPtr = RigidBodies.at(j);  // Not recognizing rigid body pointer correctly
//std::cout << rPtr->dt << 'n';
Polygon * polyPtr = rPtr->p;
std::cout << "hey1" << 'n';
int size = polyPtr->Points.size();  // ERROR HERE //
std::cout << "hey2" << 'n';
//  std::cout << polyPtr->Points.at(0)->y << 'n';
for (int i = 0; i < size; i++) {
std::cout << "hey3" << 'n';
auto pointPtr1 = polyPtr->Points.at(i);
int lastIndex = size - 1;
//std::cout << i+1 << 'n';
auto pointPtr2 = polyPtr->Points.at((i + 1) % (lastIndex));  // Modulo so last point links back up to first one.
SDL_RenderDrawLine(renderer, (rPtr->position.x + pointPtr1->x) * scale, SCREEN_HEIGHT 
- (rPtr->position.y + pointPtr1->y) * scale, (rPtr->position.x + pointPtr2->x) * scale,
SCREEN_WIDTH - (rPtr->position.y + pointPtr2->y * scale));
}
}
SDL_RenderPresent(renderer);
}

渲染.h:

#include <vector>
#include <SDL2/SDL.h>
#ifndef RENDERING_H
#define RENDERING_H
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
//SDL_Renderer * renderer; 
SDL_Renderer* InitializeRender();
void Render(SDL_Renderer*, std::vector<RigidBody*>);
#endif

rigid_bodies.cpp

// Joaquin Matias Giorgi jmgiorgi@bu.edu Impulse-Based Physics Engine 2D //
#include <iostream>
#include <math.h>
#include <SDL2/SDL.h>
#include <vector>
#include "polygon.h"
using namespace std;
vector<RigidBody*> RigidBodies;
// VECTOR STUFF //
// Multiplication by scalar quantity.
Vector Vector::operator*(const float scalar) {
Vector vout;
vout.x = this->x * scalar;
vout.y = this->y * scalar;
return(vout);
}
// Addition overload.
Vector Vector::operator+=(const Vector vec) {
Vector vout;
vout.x = this->x + vec.x;
vout.y = this->y + vec.y;
return(vout);
}
float dot (Vector vec1, Vector vec2) {
float out = (vec1.x * vec2.x) + (vec1.y * vec2.y);
return(out);
}
float cross2d (Vector vec1, Vector vec2) {
// magnitude of perpendicular vector in 3d case.
float out = (vec1.x * vec2.y) - (vec1.y * vec2.x);
return(out);
}
// POLYGON Struct Methods //
Polygon::Polygon(vector< Vector* > Points1, Material m1, float volume1) {
Points = Points1;
m = m1;
volume = volume1;
}
float Polygon::ComputeMass() {
float mass = m.density * this->volume;
return(mass);
}
// RIGID BODY Struct Methods //
RigidBody::RigidBody(Vector position1, Polygon * p1) {
std::cout << test << 'n';
position = position1;
p = p1;
mass = p1->ComputeMass();
orientation = 0;
angularVelocity = 0;
dt = .033;
gravity.x = 0;
gravity.y = -9.8;
velocity.x = 0;
velocity.y = 0;
//RigidBodies.push_back(this); // Push to global vector of all RigidBodies.
}
// UPDATE at each iteration.  
void RigidBody::Step() {
this->velocity += this->gravity * this->dt;
this->position += this->velocity * this->dt;
this->orientation += this->angularVelocity * this->dt;
}

多边形.h:

#include <vector>
#ifndef POLYGON_H
#define POLYGON_H
struct Vector {
float x;
float y;
// Multiplication by scalar quantity.
Vector operator*(const float);
// Addition overload.
Vector operator+=(const Vector);
};
struct Material {
float density;
float restitution;
};
struct Polygon {
std::vector< Vector* > Points;
float volume;
Material m;
Polygon(std::vector< Vector* >, Material, float);
float ComputeMass();
};
struct RigidBody {
float mass;
float volume;
float dt;
// Linear
Vector position;
Vector gravity;
Vector velocity;
float acceleration;
// Angular
float orientation;
float angularVelocity;
float torque;
Polygon * p;
// Constructor
RigidBody(Vector, Polygon*);
// UPDATE at each iteration.  
void Step();
};
// DECLARATION
extern std::vector<RigidBody*> RigidBodies;  // Global Vector of RigidBody Pointers.

#endif

制作文件:

sim: 
g++ -std=c++11 main.cpp rigid_bodies.cpp rendering.cpp -I include -L lib -l SDL2-2.0.0

在函数CreateBody中,RigidBody r1在堆栈上创建,并在函数返回时不复存在。您的指针rigPtr(以及PointspolPtr中的指针(在函数结束后不再有效。如果在循环中调用CreateBody,您可能会看到每次调用都会获得相同的指针。

最简单的解决方案是根本不使用指针,您的对象相当小,复制成本不应太高(甚至移动成本更低(。

如果你真的想使用指针,你需要在堆上分配对象,而不是使用new在堆栈上分配对象。请注意,这些对象随后需要使用delete解除分配。更安全的解决方案是将指针包装在std::shared_ptrstd::unique_ptr中,以自动删除对象。

最新更新