为什么我的向量在 C++ 中存储我的对象的副本,而不是原始值?

Why does my vector store a copy of my object, and not the original value, in c++?

我有一项期中作业,其中我们对课程中的一个程序进行 3 组单元测试以及文档等。我选择的项目是物理模拟。

在此程序中,有两个 类、ThingWorld。我能够独立地创建这些对象。我尝试通过创建 std::vector<Thing> thingsThing 对象添加到 World 对象,然后创建一个函数将 Thing 添加到 vector 对象。但是,当我这样做时,似乎 World 对象创建了自己的 Thing 副本,因为当我更改 Things 位置时,[=11] 的版本=] 在 things 向量中保持不变。

请就此事提供一些指导,我觉得我的问题可能在于我在这种情况下如何使用指针。

 void testBoundaryBounce()
 {
      //Create the world
      World world{10.0f, 10.0f, 1.0f};
      //Thing, 2 units away from boundary
      Thing thing{8.0f, 5.0f, 1.0f};
      //Add thing to world (adding it the the things vector)
      world.addThing(&thing);
      //Apply force that should trigger bounce back to x = 7
      thing.applyForce(1.0f, 0.0f);
      //Updating thing so that movement takes effect
      thing.update();
      //Running world update to account for collisions, bounces etc
      world.update();

      std::cout << "thing x : " << thing.getX() << std::endl;

      CPPUNIT_ASSERT(thing.getX() == 7);
 }


Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{

}


World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
    std::vector<Thing> things;
}



void World::addThing(Thing* thing)
{
    float thingX = thing->getX();
    float thingY = thing->getY();
    float thingRad = thing->getRad();

    std::cout << "Radius : " << thingRad << std::endl;

    if (thingX + thingRad > width || thingX - thingRad <= 0 || thingY + thingRad > 
    height|| thingY - thingRad <= 0)
    {
        std::cout << "Thing is out of bounds or is too large" << std::endl;
    }
    else {
        std::cout << "Thing is good" << std::endl;
        things.push_back(*thing);
    }
}

void World::update()
{
    for (Thing& thing : things)
    {
        thing.update();
        float thingX = thing.getX();
        float thingY = thing.getY();
        float thingRad = thing.getRad();
        float worldGrav = this->gravity;

        std::cout << "thing x: " << thingX << std::endl;
        std::cout << "thing rad: " << thingRad << std::endl;

        //World Boundary Bounces
        if (thingX + thingRad >= width)
        {
            std::cout << "Bounce left" << std::endl;
            thing.applyForce(-2.0f, 0.0f);
            thing.update();
        }
        if (thingX + thingRad <= 0)
        {
            thing.applyForce(2.0f, 0.0f);
            thing.update();
            std::cout << "Bounce right" << std::endl;
        }
        if (thingY + thingRad >= height)
        {
            thing.applyForce(0.0f, -2.0f);
            thing.update();
            std::cout << "Bounce up" << std::endl;
        }
        if (thingY - thingRad <= 0)
        {
            thing.applyForce(0.0f, 2.0f);
            thing.update();
            std::cout << "Bounce down" << std::endl;
        }
        //Thing Collision Bounces
        for (Thing& otherthing : things)
        {
            float thing2X = otherthing.getX();
            float thing2Y = otherthing.getY();
            float thing2Rad = otherthing.getRad();
            if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad == 
                thing2Y + thing2Rad)
            {
                thing.applyForce(-2.0f, -2.0f);
                thing.update();
                otherthing.applyForce(2.0f, 2.0f);
                otherthing.update();
            }
        }
        //Gravitational Pull
        thing.applyForce(0.0f, worldGrav);
    }
}

它在 void push_back (const value_type& val);the definition 中...

Adds a new element at the end of the vector, after its current last element. The content of val is copied (or moved) to the new element.

所以当您调用 things.push_back(*thing); 时,您正在向 'things' 向量添加一个新元素,它是 thing 指针指向的值的副本。

您想更改向量以保存指向 Thing 类型的指针:

std::vector<Thing *> things;

并添加指针而不是副本:

things.push_back(thing);

请注意,您稍后必须通过 -> 而不是 . 访问字段,或者您可以创建对它的引用,例如:

    for (Thing* pt: things)
    {
        Thing& thing = *pt; 
        thing.update();
        //etc...

您可以 World 构建它拥有的 Thing,而不是构建 Thing 并将其复制到 world

void testBoundaryBounce()
 {
      //Create the world
      World world{10.0f, 10.0f, 1.0f};
      //Thing, 2 units away from boundary
      Thing * thing = world.addThing(8.0f, 5.0f, 1.0f);
      //Apply force that should trigger bounce back to x = 7
      thing->applyForce(1.0f, 0.0f);
      //Running world update to account for collisions, bounces etc
      //Implies updating all the things
      world.update();

      std::cout << "thing x : " << thing.getX() << std::endl;

      CPPUNIT_ASSERT(thing.getX() == 7);
 }


Thing::Thing(float x, float y, float radius)
: x{x}, y{y}, dX{0}, dY{0}, radius{radius}
{

}


World::World(float width, float height, float gravity)
: width{width}, height{height}, gravity{gravity}
{
    std::vector<Thing> things;
}



Thing * World::addThing(float x, float y, float radius)
{
    std::cout << "Radius : " << radius << std::endl;

    if ((x + radius > width) || (x - radius <= 0) || (y + radius > 
    height) || (y - radius <= 0))
    {
        std::cout << "Thing is out of bounds or is too large" << std::endl;
        return nullptr;
    }
    else 
    {
        std::cout << "Thing is good" << std::endl;
        return &things.emplace_back(x, y, radius);
    }
}

void World::update()
{
    for (Thing& thing : things)
    {
        thing.update();
        float thingX = thing.getX();
        float thingY = thing.getY();
        float thingRad = thing.getRad();
        float worldGrav = this->gravity;

        std::cout << "thing x: " << thingX << std::endl;
        std::cout << "thing rad: " << thingRad << std::endl;

        //World Boundary Bounces
        if (thingX + thingRad >= width)
        {
            std::cout << "Bounce left" << std::endl;
            thing.applyForce(-2.0f, 0.0f);
            thing.update();
        }
        if (thingX + thingRad <= 0)
        {
            thing.applyForce(2.0f, 0.0f);
            thing.update();
            std::cout << "Bounce right" << std::endl;
        }
        if (thingY + thingRad >= height)
        {
            thing.applyForce(0.0f, -2.0f);
            thing.update();
            std::cout << "Bounce up" << std::endl;
        }
        if (thingY - thingRad <= 0)
        {
            thing.applyForce(0.0f, 2.0f);
            thing.update();
            std::cout << "Bounce down" << std::endl;
        }
        //Thing Collision Bounces
        for (Thing& otherthing : things)
        {
            float thing2X = otherthing.getX();
            float thing2Y = otherthing.getY();
            float thing2Rad = otherthing.getRad();
            if (thingX + thingRad == thing2X + thing2Rad && thingY + thingRad == 
                thing2Y + thing2Rad)
            {
                thing.applyForce(-2.0f, -2.0f);
                thing.update();
                otherthing.applyForce(2.0f, 2.0f);
                otherthing.update();
            }
        }
        //Gravitational Pull
        thing.applyForce(0.0f, worldGrav);
    }
}

顺便说一句,每次更新都会自行反弹