从映射中检索对象实例 我是C++新手,我想做一个小游戏。我有一个名为UnitController的类,它在一个映射中存储类Unit的多个实例。该类还有一个getUnit方法,它应该返回一个存储的单元

从映射中检索对象实例 我是C++新手,我想做一个小游戏。我有一个名为UnitController的类,它在一个映射中存储类Unit的多个实例。该类还有一个getUnit方法,它应该返回一个存储的单元,c++,C++,这种方法似乎只起了部分作用。我想我得到的是单元的副本,而不是请求的实例 有人能给我指出正确的方向吗 #include "UnitController.h" #include "Unit.h" using namespace ci; using std::map; UnitController::UnitController() { } void UnitController::addUnit( Vec2f position ) { Unit mUnit = Unit();

这种方法似乎只起了部分作用。我想我得到的是单元的副本,而不是请求的实例

有人能给我指出正确的方向吗

#include "UnitController.h"
#include "Unit.h"

using namespace ci;
using std::map;

UnitController::UnitController()
{
}

void UnitController::addUnit( Vec2f position )
{
    Unit mUnit = Unit();
    mUnit.setup( position );
    Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
}

Unit UnitController::getUnit( int k )
{
    Unit selectedUnit = Units[0];
    return selectedUnit;
}

void UnitController::update()
{
    for( map<int,Unit>::iterator u = Units.begin(); u != Units.end(); ++u ){
        u->second.update();
    }
}

void UnitController::draw()
{
    for( map<int,Unit>::iterator u = Units.begin(); u != Units.end(); ++u ){
        u->second.draw();
    }
}
方法:

Unit UnitController::getUnit( int k )
{
    Unit selectedUnit = Units[0];
    return selectedUnit;
}
是否返回索引为0的元素的副本(可能是默认副本)?。如果希望避免返回副本,请返回对索引0处元素的引用,而不是对局部变量selectedUnit的引用:

如果从映射中删除了由k键控的条目,那么具有对条目单元的引用的调用方现在具有悬空引用,使用该引用是未定义的行为。有一些事情要考虑避免这种情况:

UnitController的客户端是否需要直接访问地图中的单元?如果不是,客户端只需要更新单元的某些属性,则修改UnitController接口以支持单元更新,而不提供客户端直接访问。 如果客户端需要直接访问,那么考虑使用STD::SysDypPTR代替条目值类型的单元,并且在这种情况下不返回引用。这将解决悬空引用问题,但调用方访问不再位于UnitController中的单元意味着什么? 将在地图中为当前不存在的密钥创建条目:

使用key作为键和默认构造的映射值向容器插入新元素,并返回对新构造的映射值的引用。如果具有key的元素已经存在,则不执行插入,并返回对其映射值的引用

如果您不希望出现这种行为,请使用并决定在密钥k的条目不存在时应采取的措施。

方法:

Unit UnitController::getUnit( int k )
{
    Unit selectedUnit = Units[0];
    return selectedUnit;
}
是否返回索引为0的元素的副本(可能是默认副本)?。如果希望避免返回副本,请返回对索引0处元素的引用,而不是对局部变量selectedUnit的引用:

如果从映射中删除了由k键控的条目,那么具有对条目单元的引用的调用方现在具有悬空引用,使用该引用是未定义的行为。有一些事情要考虑避免这种情况:

UnitController的客户端是否需要直接访问地图中的单元?如果不是,客户端只需要更新单元的某些属性,则修改UnitController接口以支持单元更新,而不提供客户端直接访问。 如果客户端需要直接访问,那么考虑使用STD::SysDypPTR代替条目值类型的单元,并且在这种情况下不返回引用。这将解决悬空引用问题,但调用方访问不再位于UnitController中的单元意味着什么? 将在地图中为当前不存在的密钥创建条目:

使用key作为键和默认构造的映射值向容器插入新元素,并返回对新构造的映射值的引用。如果具有key的元素已经存在,则不执行插入,并返回对其映射值的引用


如果您不希望出现这种行为,请使用并决定在密钥k的条目不存在时应采取的措施。

您确实会收到单元的深度副本


考虑创建一个引用计数指针,也称为封装单位的智能指针,并将其设置为映射的值类型。

您确实会收到单位的深度副本


考虑创建一个引用计数指针,也称为封装单元的智能指针,并将其设置为映射的值类型。

当然,您可以获得副本。考虑这一点:

void UnitController::addUnit( Vec2f position )
{
    Unit mUnit = Unit();     // you create local instance of Unit
    mUnit.setup( position );
    // you add it to the map - actually the copy is created and stored in map
    Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
    // mUnit is destroyed after the function exits
    // your map would now contain a destroyed object if it wasn't a copy
}
此外,getUnit方法还返回一个副本。这可能是正确的,也可能是错误的,这取决于客户机如何处理它。如果它改变了返回的单元实例的状态,那么它将不会反映在带有映射的副本中

您可能想使用map,但需要考虑原始对象的生存期。您不能销毁它,因为指针将指向已销毁的对象。因此,正确的解决方法是使用


但是,您的设计还有其他问题。将当前大小+1存储为映射键,这意味着将其用作索引。为什么不直接使用std::vector呢?

当然你会得到副本。考虑这一点:

void UnitController::addUnit( Vec2f position )
{
    Unit mUnit = Unit();     // you create local instance of Unit
    mUnit.setup( position );
    // you add it to the map - actually the copy is created and stored in map
    Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
    // mUnit is destroyed after the function exits
    // your map would now contain a destroyed object if it wasn't a copy
}
此外,getUnit方法还返回一个副本。这可能是正确的,也可能是错误的,这取决于客户机如何处理它。如果它改变了返回的单元实例的状态,那么它将不会反映在带有映射的副本中

您可能想使用map,但接下来您需要注意映射的生命周期 原始对象。您不能销毁它,因为指针将指向已销毁的对象。因此,正确的解决方法是使用

但是,您的设计还有其他问题。将当前大小+1存储为映射键,这意味着将其用作索引。为什么不直接使用std::vector呢?

在这段代码中:

您按值返回单位,因此实际上可以得到原始单位的副本

还请注意,您似乎有一个bug,因为您使用0作为键,而不是参数k

如果要修改原始单位,即地图中存储的单位,可以通过引用单位返回&:

作为旁注,您可以简化插入代码。而不是使用std::map::insert方法:

在此代码中:

您按值返回单位,因此实际上可以得到原始单位的副本

还请注意,您似乎有一个bug,因为您使用0作为键,而不是参数k

如果要修改原始单位,即地图中存储的单位,可以通过引用单位返回&:

作为旁注,您可以简化插入代码。而不是使用std::map::insert方法:


如果k>=Units.size怎么办-@用户1764961,这是一个映射,不是向量或数组。我认为OP不会对这种行为感到满意。@user1764961,我不明白你的意思。如果k>Units.size不相关。重要的是该映射是否包含键为k的条目,以及OP在这种情况下想要的行为。这个答案说明了这一点,并提供了使用运算符[]的替代方法。如果k>=Units.size怎么办-@用户1764961,这是一个映射,不是向量或数组。我认为OP不会对这种行为感到满意。@user1764961,我不明白你的意思。如果k>Units.size不相关。重要的是该映射是否包含键为k的条目,以及OP在这种情况下想要的行为。该答案说明了这一点,并提供了使用运算符[]的替代方法。
Unit& UnitController::getUnit(int key)
{
    return Units[k];
}
Units.insert( std::pair<int,Unit>( Units.size()+1, mUnit ) );
Units[ ...the key here... ] = mUnit;