将正常指针强制转换为std :: shared_ptr似乎不起作用

时间:2012-12-09 12:39:02

标签: c++ pointers casting c++11 shared-ptr

#include <SFML/Graphics.hpp>
#include <memory>
#include <map>

int main(int argc, char **argv)
{
std::map <const std::string, std::shared_ptr<sf::Texture> > resources;
sf::Texture tempResource;
tempResource.loadFromFile("1.PNG");

resources.insert(std::pair<const std::string, std::shared_ptr<sf::Texture>>("1", std::dynamic_pointer_cast<sf::Texture>( new sf::Texture(tempResource) ) ) );

return 0;
}

(新调用使用复制构造函数)

没有强制转换(只是调用新的内部插入函数)它没有工作。所以我使用shared_ptr强制转换来做它,但它不起作用。错误: 错误:没有匹配函数来调用'dynamic_pointer_cast(sf :: Texture *)'

这里有什么问题,我怎样才能让它发挥作用?我是shared_ptrs的新手,我自己也无法自行解决。

由于

2 个答案:

答案 0 :(得分:0)

你应该说:

std::map<std::string, std::shared_ptr<sf::Texture>> resources;
      // ^^^ "const" is redundant

// ...

resources.insert(std::make_pair("1", std::make_shared<sf::Texture>(tempResource)));

如果您的平台支持它,您甚至可以说:

resources.emplace("1", std::make_shared<sf::Texture>(tempResource));

或者:

resources.emplace("1", new sf::Texture(tempResource));

但这不如make_shared那么好,效率更高,并且违反了从不使用new的良好品味规则。无论哪种方式,emplace的要点是它允许显式构造函数,与insert不同。


甚至更好的是,根本不使用临时的:

resources.emplace("1", std::make_shared<sf::Texture>()).second->loadFromFile("1.PNG");

答案 1 :(得分:0)

您要做的是从以前的非托管内存创建shared_ptrdynamic_pointer_cast不是工作的工具。相反,这应该工作:

resources.insert(std::pair<const std::string, std::shared_ptr<sf::Texture>>("1", std::shared_ptr<sf::Texture>(new sf::Texture(tempResource)));
//or:
resources.insert(std::make_pair("1", std::shared_ptr<sf::Texture>(new sf::Texture(tempResource)));

但是,从新分配的内存中构造shared_ptr有点浪费。因为这会进行两次分配(一次用于内存,一次用于shared_ptr的内部数据)。如果您使用std::make_shared(tempResource),那么这两个分配可以组合成一个以提高效率。

C ++ 11还允许resources.emplace("1", std::make_shared(tempResource)进行对的原位构造,但是上次我检查编译器支持时有点缺乏​​。

作为旁注:如果您不再需要tempResource,则可能需要考虑移动(而不是使用std::move(tempResource)代替tempResource将其复制到数据结构中构造新分配的对象。根据sf::texture的实现,这可能(或可能不)更有效。如果对象不是真正可移动构造的(因此移动构造基本上与副本相同) ,您可能希望将Texture直接构建到shared_ptr并在该帐户上调用load:

auto tempResource = std::make_shared<sf::Texture>();
tempResource->loadFromFile("1.PNG");
resources.emplace("1",std::move(tempResource));//or insert if emplace isn't availible