[英]Why does my vector store a copy of my object, and not the original value, in c++?
我有一个中期任务,我们为我们课程中的一个程序进行 3 组单元测试和文档等。 我选择的程序是物理模拟。
在这个程序中,有两个类, Thing
和World
。 我能够独立创建这些对象。 我尝试通过创建std::vector<Thing> things
将Thing
object 添加到World
object ,然后创建vector
以将Thing
添加到 things. 但是,当我这样做时,似乎World
object 创建了自己的Thing
副本,因为当我更改Thing
的 position 时,Thing 向量中的Thing
版本保持不变。
请就此事提供一些指导,我觉得我的问题可能在于我在这种情况下如何使用指针。
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);
的定义中是正确的; ...
在当前最后一个元素之后,在向量的末尾添加一个新元素。 val 的内容被复制(或移动)到新元素。
所以当你打电话给things.push_back(*thing);
,您正在向“事物”向量添加一个新元素,该元素是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);
}
}
顺便说一句,每次更新都会自动反弹
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.