如何从另一个向量/对象集构造一个新的向量/指针集?

时间:2016-08-22 20:51:29

标签: c++ c++11 pointers vector set

背景

我想操纵向量的副本,但是对其每个元素执行向量复制操作通常是昂贵的操作。

有一个叫做浅拷贝的概念,我在某处读到的是默认的拷贝构造函数行为。但是,我不确定为什么它不起作用,或者至少我试图做矢量对象的副本,结果看起来像一个深层副本。

    private List<string> GetLinks(string message)
    {
        List<string> list = new List<string>();
        Regex urlRx = new Regex(@"((http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", RegexOptions.IgnoreCase);

        MatchCollection matches = urlRx.Matches(message);
        foreach (Match match in matches)
        {
            if(!match.ToString().Contains("news.google.com/news") && !match.ToString().Contains("google.com/alerts"))
            {
                string find = "=http";
                int ind = match.ToString().IndexOf(find);                    
                list.Add(match.ToString().Substring(ind+1));
            }                
        }
        return list;
    }        

天真的解决方案:用于指针复制。

struct Vertex{
    int label;
    Vertex(int label):label(label){ }
};

int main(){
    vector<Vertex> vertices { Vertex(0), Vertex(1) };

    // I Couldn't force this to be vector<Vertex*>      
    vector<Vertex> myvertices(vertices); 

    myvertices[1].label = 123;

    std::cout << vertices[1].label << endl; 
    // OUTPUT: 1 (meaning object is deeply copied)

    return 0;
}

改进

是否还有其他更好的方法或int main(){ vector<Vertex> vertices { Vertex(0), Vertex(1) }; vector<Vertex*> myvertices; for (auto it = vertices.begin(); it != vertices.end(); ++it){ myvertices.push_back(&*it); } myvertices[1].label = 123; std::cout << vertices[1].label << endl; // OUTPUT: 123 (meaning object is not copied, just the pointer) return 0; } API来构建一个新的向量,其中包含原始向量中每个元素的指针

2 个答案:

答案 0 :(得分:2)

一种方法是将元素向量转换为指针向量,指向原始向量的元素,与示例相比,效率更高,因为它预先分配了向量的缓冲区指针和恕我直言更优雅是通过使用std::transform如下:

std::vector<Vertex*> myvertices(vertices.size());
std::transform(vertices.begin(), vertices.end(), myvertices.begin(), [](Vertex &v) { return &v; });

Live Demo

或者,如果您不想将lambda用于一元运算符:

std::vector<Vertex*> myvertices(vertices.size());
std::transform(vertices.begin(), vertices.end(), myvertices.begin(), std::addressof<Vertex>);

Live Demo

警告:如果您更改了原始矢量,那么您将使指针中的指针无效&#39;矢量。

答案 1 :(得分:0)

感谢@kfsone注意到主要问题,人们想要从另一个对象向量中跟踪指针而不利用其背后的核心思想是非常罕见的。他提供了一种通过使用位掩码来解决类似问题的替代方法。在他提到这一点之前,对我来说可能并不明显。

当我们试图存储另一个向量的指针时,我们很可能想要对另一个对象进行一些跟踪,保持(保持跟踪)。稍后将在不触及原始数据的情况下对指针本身执行。就我而言,我通过强力方法解决了最小顶点覆盖问题。因此,我将需要生成顶点的所有排列(例如,20个顶点将生成2 ** 20 = 1百万++排列),然后通过缓慢迭代顶点封面中的每个顶点并删除所覆盖的边缘来减少所有无关排列。顶点。在这样做时,我的第一个直觉是复制所有指针以确保效率,之后我可以逐个删除指针。

然而,研究这个问题的另一种方法是根本不使用vector / set,而只是将每个指针跟踪为一个位模式。我不打算详细介绍,但我可以随意learn from others

性能差异非常显着,因此按位,你可以实现O(1)恒定时间而没有太大问题,而使用特定容器,你往往必须迭代将算法绑定到O的每个元素( N)。为了使它变得更糟,如果你正在强制NP难问题,你需要保持尽可能低的常数因子,从O(1)到O(N)是这种情况的巨大差异。