c++ - 对象指针的全局向量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
刚体.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
(以及 and 中的指针Points
)polPtr
不再有效。如果您CreateBody
在循环中调用,您可能会看到每次调用都获得相同的指针。
最简单的解决方案是根本不使用指针,您的对象相当小,复制成本不应该太高(甚至移动成本也不高)。
如果您真的想使用指针,则需要在堆上分配对象,而不是使用new
. 请注意,这些对象将需要使用delete
. 一个更安全的解决方案是将指针包装在其中,std::shared_ptr
或者std::unique_ptr
自动删除对象。
推荐阅读
- unicode - 将 unicode 字符添加到 Cognos Analytics 表达式数据
- terraform - Terraform - 变量内的变量
- microsoft-graph-api - 使用 Microsoft graph 查询提取的数据
- reactjs - 使用 useEffect 时挂钩调用无效
- django - 计数注释为所有字段添加不需要的分组语句
- sql-server - 带有返回重复最小值的 GROUP BY 的 SQL 子查询。外部查询如何解释这个?
- python - 使用 beautifulsoup 抓取图像时出错
- javascript - React Native:可能未处理的承诺拒绝(id:0)TypeError:网络请求失败
- javascript - console.log() JSON 对象中的特定值
- android - kotlin.UninitializedPropertyAccessException:lateinit 属性 roomClickedInterface 尚未初始化