我正在使用SFML和c ++ 11进行这个简单的教程。我正在教授地图容器。我有c#知识,我的理解是地图与字典相同。我的问题是他提供的代码片段,但不能很好地解释。
TextureHolder.h
std::map<std::string, sf::Texture> m_textures;
TextureHolder.cpp
sf::Texture& TextureHolder::GetTexture(std::string const& filename)
{
auto& r_textures = m_s_instance -> m_textures;
auto keyValuePair = r_textures.find(filename);
if (keyValuePair != r_textures.end())
{
return keyValuePair->second;
}
else
{
auto& texture = r_textures[filename];
texture.loadFromFile(filename);
return texture;
}
}
我理解除了else语句之外的所有内容。这是我对最新情况的理解,但是如果有人能向我澄清实际发生了什么以及为什么我错了,我会很感激。
auto& texture = r_textures[filename]
这将使用filename的密钥创建一个新的键值对。然后它将值赋给纹理,这是一个空值,因为没有加载纹理。
texture.loadFromFile(filename);
这会加载纹理文件并将其指定给纹理。这是我完全迷失的地方。这条线的某种方式也是将纹理添加到键的值。
然后它将纹理返回给调用函数。
这可能更多地是对SFML如何处理纹理对象的误解,但我仍然对这条线如何与地图中的键值对进行通信感到困惑。
答案 0 :(得分:4)
自动&安培; texture = r_textures [filename]这将创建一个新的键值对 用文件名的键。然后它将值赋给纹理,其中 是一个空值,因为没有加载纹理。
不完全正确。 texture
是一个参考。它本身并不是一个谨慎的对象。
这将创建一个新的键/值对,并在地图中设置引用texture
以引用新创建的值。
后续loadFromFile()
通过loadFromFile()
引用调用texture
方法。这恰好引用了地图中新插入的值。
然后,返回对从文件中新加载的值的引用。
胶囊摘要:它搜索地图以查看是否找到了密钥,如果是,则返回对密钥值的引用。否则,它会为该键创建一个新的键/值对,初始化新值,然后返回它。
答案 1 :(得分:3)
auto& texture = r_textures[filename]
这将使用filename的密钥创建一个新的键值对。然后它将值赋给纹理,这是一个空值,因为没有加载纹理。
它不会将值分配给texture
。它使texture
成为对新创建的纹理的引用。这就是&
中的auto&
所做的。
texture.loadFromFile(filename);
这会加载纹理文件并将其指定给纹理。这是我完全迷失的地方。这条线的某种方式也是将纹理添加到键的值。
它不会将其分配给texture
,而是将其分配给texture
引用的对象 - 请记住,texture
是参考。它指的是地图中的纹理。
然后它将纹理返回给调用函数。
实际上,它会返回对它的引用。请记住,返回类型为sf::Texture&
。
答案 2 :(得分:2)
在本声明中
auto& texture = r_textures[filename];
在地图中创建了一个新对,其键等于filename
,映射值等于通过调用默认构造函数sf::Texture()
创建的对象。并且运算符返回对创建的映射值的引用。此引用存储在变量texture
中,而变量texture.loadFromFile(filename);
又是引用。因此,此引用引用映射类型的原始默认创建对象。
然后更新存储在地图中的映射类型的原始对象
texture
因为变量return texture;
是对象的引用。
最后,从函数
返回此引用,该引用是对地图中原始映射对象的引用operator []
因此StringCaseSense, on
StringGetPos, OutputVar, Clipboard, book
msgbox, %OutputVar%
或者返回对映射对象的引用,如果对应于指定键的对象已经存在于映射中,或者创建一个新的映射对象,调用其默认构造函数并返回对该映射对象的引用。新创建的映射对象。
答案 3 :(得分:1)
其他答案解释了您发布的代码。
但是,正如我的评论建议的那样,使用std::map::insert()代替find()
然后使用[]
可能会使代码更清晰。诀窍是知道std::map::insert
返回什么以及如何使用它。
sf::Texture& TextureHolder::GetTexture(std::string const& filename)
{
auto& r_textures = m_s_instance -> m_textures;
// potentially insert a new texture. If not inserted, then the
// current one remains in the map
auto ret = r_textures.insert(std::make_pair(filename, sf::Texture()));
// ret is a std::pair<map::iterator, bool>, where map::iterator is
// the iterator to the existing or newly inserted item. The second
// is a bool that is either true or false, depending on whether new item
// was inserted or not.
// Now get the texture. A map's iterator is itself a pair, so
// 'first' of this pair is the filename, and 'second' is the texture.
auto& texture = ret.first->second;
// this tells us if it's a new item inserted
if ( ret.second )
texture.loadFromFile(filename);
return texture;
}
这基本上与您的版本做同样的事情,只是它使用map::insert
来确定是否插入了新项目并使用了insert
的返回值。
请注意,map::insert
需要std::pair
由“潜在”新密钥和值组成(它是“潜在”,因为我们不知道是否会插入新密钥 - 我们使insert()决定)。
如果密钥已经存在,那么insert
除了返回迭代器/布尔对之外什么都不做。如果密钥不存在,那么insert
默认情况下会插入一个全新的sf::Texture
构建一个(参见make_pair
的第二个参数),然后返回迭代器/ bool对