将临时std :: shared_ptr插入std :: map,不好吗?

cod*_*ddy 3 c++ c++11

我正在为我的应用程序设计一个类,它实现了许多标准的共享指针和标准容器的使用,例如std :: mapstd :: vector

这是问题的非常具体的问题,所以我只是为了澄清目的从我的标题中复制了一段代码.这里是标题中声明的快照:

struct Drag;
std::map<short, std::shared_ptr<Drag>> m_drag;
typedef sigc::signal<void, Drag&> signal_bet;
inline signal_bet signal_right_top();
Run Code Online (Sandbox Code Playgroud)

这是使用上述声明的函数之一和临时的shared_ptr,它不仅用于此函数,还用于某个较晚的时间.这意味着在函数返回后,共享指针仍应处于活动状态,因为它将在某个时刻分配给另一个shared_ptr.

void Table::Field::on_signal_left_top(Drag& drag)
{
    m_drag.insert(std::make_pair(drag.id, std::make_shared<Drag>(this))); // THIS!
    auto iter = m_drag.find(drag.id);
    *iter->second = drag;
    iter->second->cx = 0 - iter->second->tx;
    iter->second->cy = 0 - iter->second->ty;

    invalidate_window();
}
Run Code Online (Sandbox Code Playgroud)

上面的函数首先插入一个新的shared_ptr,然后将值从一个对象分配到另一个对象,

我的答案就是要告诉我们将临时的shared_ptr插入地图是否安全,并确保它不会是悬空或什么坏事.

根据网站,上述功能不被认为是安全的,因为写它会更好:

void Table::Field::on_signal_left_top(Drag& drag)
{
    std::shared_ptr pointer = std::make_shared<Drag>(this);
    m_drag.insert(std::make_pair(drag.id, pointer));
    auto iter = m_drag.find(drag.id);
    *iter->second = drag;
    // etc...
 }
Run Code Online (Sandbox Code Playgroud)

在函数中更多一行.

它真的需要这样打字,为什么?

Som*_*ude 9

两个函数之间没有区别std::shared_ptr,因为该std::make_pair函数将在临时对象被销毁之前创建临时对象的副本.该副本将被复制到std::map,然后本身将被破坏,留下你在地图中的副本副本.但由于其他两个对象已被破坏,因此地图中对象的引用计数仍为1.


至于处理返回值insert,它很简单:

auto result = m_drag.insert(...);
if (!result.second)
{
    std::cerr << "Could not insert value\n";
    return;
}

auto iter = result.first;

...
Run Code Online (Sandbox Code Playgroud)