编译错误向量排序和联合



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

#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);

分析

在概念之前,在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()end() const std::vector<uint32_t>的方法都返回 std::vector<uint32_t>::const_iterator

您不能通过const_iterator写作。

解决方案

如果您愿意修改p1p2参考的对象,则可以将它们作为引用作为可修改的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;
}

否则,您需要处理向量的副本。您可以按值将p1p2传递,但是通常,您应该只需将所需的内容(在这种情况下,将其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;

#include <algorithm>
#include <cstdint>
#include <vector>
struct Point {
    std::vector<uint32_t> 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;
} 
int main () {
    Point p1, p2;
    std::vector<uint32_t> res = inter_section(p1, p2);
}

最新更新