编译错误Vector Sort和Union

时间:2017-05-04 15:23:18

标签: c++ vector

我有一个简单的程序,它生成两个点(由整数向量组成)并找到两个不同点的两个向量的并集。但是有一些奇怪的编译错误,我无法弄清楚。

#include <iostream>     // std::cout
#include <algorithm>    // std::set_union, std::sort
#include <vector>       // std::vector
#include <stdio.h>
#include <stdint.h>
#include <cstdint>

using namespace std;
struct Point {
    std::vector<uint32_t> vec;
};

vector<uint32_t> inter_section( const Point& p1, const Point& p2 )
{
    vector<uint32_t> v3;

    sort(p1.vec.begin(), p1.vec.end());
    sort(p2.vec.begin(), p2.vec.end());

    set_intersection(p1.vec.begin(),p1.vec.end(),p2.vec.begin(),p2.vec.end(),back_inserter(v3));

    return v3;
}


int main () {
  Point p1, p2;
  vector<uint32_t> res = inter_section(p1, p2);

  return 0;
}

编译错误是

In file included from /usr/include/c++/4.8.2/algorithm:62:0,
                 from testUnion.cpp:3:
/usr/include/c++/4.8.2/bits/stl_algo.h: In instantiation of ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const unsigned int*, std::vector<unsigned int> >]’:
/usr/include/c++/4.8.2/bits/stl_algo.h:2211:62:   required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator) [with _RandomAccessIterator = __gnu_cxx::__normal_iterator<const unsigned int*, std::vector<unsigned int> >]’
/usr/include/c++/4.8.2/bits/stl_algo.h:5462:47:   required from ‘void std::sort(_RAIter, _RAIter) [with _RAIter = __gnu_cxx::__normal_iterator<const unsigned int*, std::vector<unsigned int> >]’
testUnion.cpp:18:38:   required from here
/usr/include/c++/4.8.2/bits/stl_algo.h:2142:17: error: assignment of read-only location ‘__first.__gnu_cxx::__normal_iterator<_Iterator, _Container>::operator*<const unsigned int*, std::vector<unsigned int> >()’
        *__first = _GLIBCXX_MOVE(__val);

1 个答案:

答案 0 :(得分:3)

分析

在概念之前的C ++中,模板方法的编译错误很难跟上它们的起源。这在未来的C ++中应该有所改进,但是现在,我们需要具备解释它们的技能。

第一个开始的地方是 required from here ,它确定哪个源代码行是问题(这里是对std::sort的调用),以及以下行,显示违反程序语义的最终操作: assignment of read-only location

为什么它是只读位置?好吧,回顾一下扩展,我们有一个__gnu_cxx::__normal_iterator<const unsigned int*, std::vector<unsigned int> >。这是std::vector<uint32_t>::const_iterator的内部表示;需要注意的重要事项是const unsigned int*,而不仅仅是unsigned int*,就像在相应的可变迭代器中一样。

为什么我们得到const_iterator?向量的begin()方法已重载;如果向量是const,我们得到一个const_iteratorend()方法也是如此。

为什么向量是常数?它来自(引用a)const Point对象。

原因摘要

该函数将p1p2作为对const Point个对象的引用。

const Point内,vec成员为const std::vector<uint32_t>

begin()的{​​{1}}和end()方法均返回const std::vector<uint32_t>

您无法通过std::vector<uint32_t>::const_iterator进行书写。

解决方案

如果您愿意修改const_iteratorp1引用的对象,可以将它们作为对可修改p2的引用传递:

Point

否则,您需要处理该向量的副本。您可以按值传递std::vector<uint32_t> inter_section(Point& p1, Point& p2) { std::sort(p1.vec.begin(), p1.vec.end()); std::sort(p2.vec.begin(), p2.vec.end()); std::vector<uint32_t> v3; std::set_intersection(p1.vec.begin(), p1.vec.end(), p2.vec.begin(), p2.vec.end(), std::back_inserter(v3)); return v3; } p1,但一般情况下,您只需将您需要的内容(在本例中为p2成员)复制到您的函数中的相应本地中:

vec

完成程序

这是程序的固定版本,减去未使用的标头和(脆弱)std::vector<uint32_t> inter_section(const Point& p1, const Point& p2) { auto v1 = p1.vec; auto v2 = p2.vec; std::sort(v1.begin(), v1.end()); std::sort(v2.begin(), v2.end()); std::vector<uint32_t> v3; std::set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(v3)); return v3; }

using namespace std;