首页 > 解决方案 > 对象指针的全局向量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

标签: c++

解决方案


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

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

如果您真的想使用指针,则需要在堆上分配对象,而不是使用new. 请注意,这些对象将需要使用delete. 一个更安全的解决方案是将指针包装在其中,std::shared_ptr或者std::unique_ptr自动删除对象。


推荐阅读