繁体   English   中英

如何使用存储在c ++中的std向量中的std :: list迭代器制作一个复制安全容器?

[英]How to make a copy safe container with std::list iterators stored in a std vector in c++?

对于我的GUI,我需要一个具有以下目的的类来管理控件(窗口,按钮等)

  • 通过[index]随机访问元素
  • 通过["key"]随机访问元素
  • 指针稳定性,所以如果添加或删除元素, ptr=&container[index]不会改变
  • 复制安全。 所有元素必须存储在容器中并复制,如果使用'='就像container2=conatiner1 (深拷贝)
  • 列表中元素的顺序必须是可更改的,但指向元素的指针必须保持有效。 如果ptr1=container[1]ptr2=container[2] ,那么在交换1和2的顺序之后, ptr1==container[2]ptr2==container[1]

我得出结论,std :: list为我需要的指针和std :: vector提供了随机访问的稳定性。 所以我有想法在向量中存储std字符串和迭代器的元组。 但是,复制容器后迭代器都无效。

关于如何最好地解决这个问题的任何建议?

这里是当前方法的主要代码(仅包括重要部分):

template < class T >
class ControlList 
{
    struct Tuple{std::string first;typename std::list<T>::iterator second;};
    std::vector<Tuple> list;
    std::list<T> objects;

    inline T& operator [](int i)
    {
        return *list[i].second;
    }
    inline T& operator [](std::string s)
    {
        loopi(0,vlist.size()) 
        if(s==vlist[i].first) 
            return *vlist[i].second;
    }
}

字符串访问速度很慢,但通常容器的元素不超过10个,并且在程序中很少使用它。

更新:

共享指针已经很好了,但无法解决我需要的深拷贝。 可以说我有window2 = window1。 现在,如果我有一个共享指针,那么按下window2中的按钮也会在window1中按下相同的按钮,这是不需要的。 我真的需要容器中包含的所有对象的新实例。

是否可以覆盖复制构造函数来创建智能指针引用的对象的新实例?

窗口和按钮都存储在ControlList ,其中窗口包含多个列表。

UPDATE2:

覆盖复制构造函数和赋值构造函数显然已经解决了这个问题

UPDATE3:

我刚刚发布了这个课程用于麻省理工学院的GUI。

在这里下载。

如果你要使用std::vector<std::pair<std::string, std::unique_ptr<T>>> ,你可以复制你想要的项目,结果值只需要一个步骤间接访问。 这将消除您现在拥有3种不同结构的大部分复杂性。 作为奖励,这些物品也会自动清理。

如果你需要使用指针的所有者 - 观察者语义,你可以改为选择std::shared_ptr<T>std::weak_ptr<T> 共享指针可以轻松创建弱指针,这些指针充当非拥有的观察者,不会影响共享指针的引用计数。

编辑:只需添加, shared_ptr和其他智能指针是C ++ 11及更高版本 - exlcusive。 如果您需要与C ++ 03兼容的解决方案,您可以查看过去的Boost实现,或者通过观察C ++ 11/14规范自己创建一个。

Edit2:这是一些协助的代码:

http://coliru.stacked-crooked.com/a/a9bf52e5428a48af

#include <vector>  //vector
#include <memory>  //smart pointers
#include <utility> //pair
#include <string>  //string
#include <iostream>//cout

template <class T>
class Container {
public:
    inline void push(const std::string& s, const T& t) {
        objects.push_back(std::pair<std::string, std::shared_ptr<T>>(s, std::make_shared<T>(t)));   
    }

    inline T& operator [](const size_t& i)
    {
        return *(objects[i]->second);
    }
    inline T& operator [](const std::string& s)
    {
        for (auto it : objects) {
            if(s == it.first) { 
                return *(it.second);
            }
        }

        //welp, what do you do here if you can't find it?
    }
private:
    std::vector<std::pair<std::string, std::shared_ptr<T>>> objects;
};

int main() {
    Container<int> cont;
    std::string str {"hi"};
    int i {2};

    cont.push(str, i);

    //This is good...
    std::cout << cont["hi"] << std::endl;

    //But undefined behavior!
    std::cout << cont["02"] << std::endl;
    return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM