std :: map中的C ++ std :: unique_ptr

时间:2014-04-25 14:35:17

标签: c++ map unique-ptr

这是:

std::unique_ptr<sf::Texture> texture;
texture = std::move(textureMap.at(id));  
return *texture;
是这样的吗?

auto found = textureMap.find(id);
return *found->second;

textureMap是:

std::map<ID, std::unique_ptr<sf::Texture>>

如果是的话,有什么更好的解决方案?

谢谢!

5 个答案:

答案 0 :(得分:2)

第一个将指针移出地图,以便在函数返回时销毁它指向的对象。如果函数返回引用,则该引用将无效。它还在地图中留下一个空指针,如果你试图取消引用它会导致问题 - 代码假定指针不为空,如果它们是,那么它将具有未定义的行为。

第二个将指针留在原位,因此对象存活。如果函数返回引用,则该引用仍然有效。但是,如果找不到钥匙,它会有未定义的行为;如果找不到密钥,它应该检查found != textureMap.end(),或者返回*textureMap.at(id)

答案 1 :(得分:1)

两个版本都不好。

第一个版本首先不必要地创建一个新的sf::Texture。然后它将纹理移出纹理贴图,这可能会破坏地图内的原始纹理。然后它返回一个不再存在的值,因为它已被unique_ptr删除。

第二个版本的问题是,如果在地图中找不到id将崩溃是UB。

更好的版本就是这样的

auto found = textureMap.find(id);
if (found != textureMap.end())
    return *found;
throw "not found error";

答案 2 :(得分:1)

如果您想避免复制较重的纹理对象,可以使sf::Texture可移动但不可复制,例如:

struct Texture
{
    Texture(Texture const&) = delete;
    Texture& operator=(Texture const&) = delete;

    Texture(Texture&&) = default;
    Texture& operator=(Texture&&) = default;
};


int main() {
    std::map<int, Texture> texture_map;
}

std::unique_ptr<>达到相同的效果,但复杂性较低。

答案 3 :(得分:1)

两者都是坏主意:

    如果找不到密钥,则
  1. at抛出,然后移动指针值(将该对的值设置为0)。
  2. 第二种情况有未定义的行为,因为如果找不到密钥,你不能解除迭代器的负担。
  3. 你可能想要的是:

    auto found = textureMap.find(id);
    if(found == textureMap.end())
        throw std::out_of_range();
    return *found->second;
    

    等于*map.at() btw。

答案 4 :(得分:1)

严格地说,除了两者都错了之外,它们并不等同。第一个版本可以抛出std::out_of_range异常,而第二个版本会在未找到密钥时调用未定义的行为。