简体   繁体   English

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

[英]Error with global vector of object pointers c++

I am developing a 2D physics engine in c++, and one of the main structures I am using is name RigidBody. 我正在用c ++开发2D物理引擎,而我正在使用的主要结构之一就是RigidBody。 In order to easily iterate through all of the RigidBody objects in each time step, I attempted to create a global vector of RigidBody object pointers. 为了在每个时间步骤中轻松遍历所有RigidBody对象,我尝试创建RigidBody对象指针的全局向量。

vector<RigidBody*> RigidBodies

As suggested in other StackOverflow answers, I declared the global variable in a header file, and defined it in one of the other project .cpp files. 正如其他StackOverflow答案中所建议的那样,我在头文件中声明了全局变量,并在其他项目.cpp文件之一中对其进行了定义。 However, when I attempt to access member functions or variables, I get bogus values. 但是,当我尝试访问成员函数或变量时,我得到了虚假值。 Below are my source and header files. 以下是我的源文件和头文件。 Could someone please let me know if there is an error with this or if I am doing something fundamentally wrong, as I have been trying to find an error for a few days, and have not been able to figure it out yet. 有人可以让我知道这是否有错误,或者我做的是根本上错误的事情,因为我已经尝试了几天,但还没有找到答案。

main.cpp: main.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);
}

rendering.cpp: rendering.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);
}

rendering.h: rendering.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 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;
    }

polygon.h: polygon.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

Makefile: Makefile文件:

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

In your function CreateBody , RigidBody r1 is created on the stack and ceases to exist when the function returns. 在您的函数CreateBodyRigidBody r1在堆栈上创建,并且在函数返回时不再存在。 Your pointer rigPtr (and the pointers in Points and polPtr ) is no longer valid after the end of the function. 函数结束后,指针rigPtr (以及PointspolPtr的指针)不再有效。 If you call the CreateBody in a loop you will probably see that you get the same pointers for every call. 如果您在循环中调用CreateBody ,则可能会看到每次调用都获得相同的指针。

The simplest solution is to not use pointers at all, your objects are fairly small and shouldn't be too expensive to copy (or even cheaper to move). 最简单的解决方案是根本不使用指针,因为您的对象非常小,并且复制不应该太昂贵(或者移动起来更便宜)。

If you really want to use pointers you need to allocate your objects on the heap rather than the stack using new . 如果您真的想使用指针,则需要在堆上分配对象,而不是使用new分配堆栈。 Note that these objects will then need to the deallocated using delete . 请注意,然后需要使用delete将这些对象释放。 A safer solution would be to wrap your pointers in std::shared_ptr or std::unique_ptr which takes care of deleting the objects automatically. 一种更安全的解决方案是将指针包装在std::shared_ptrstd::unique_ptr ,以自动删除对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM