这是:
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>>
如果是的话,有什么更好的解决方案?
谢谢!
答案 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)
两者都是坏主意:
at
抛出,然后移动指针值(将该对的值设置为0)。你可能想要的是:
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
异常,而第二个版本会在未找到密钥时调用未定义的行为。