我有一个2 * N整数的数据数组,表示对,即使i = 0,2,4,...,2 * N(对[i],对[i + 1])是这样一对。数据的格式是这样的,因为我使用的是Matlab的mex库。我这样做:
int N=5;
int data[10] = {1,2,3,4,5,6,7,8,9,10};
struct Pair { int first; int second; };
Pair * pairs = (Pair *)data;
但问题是没有办法保证Pair按顺序排列为第一,第二顺序为两个sizeof(整数)。请参阅:Is the member field order of a class "stable"?
我不想处理并将所有数据复制到新数组中,因为它不是必需的,我需要(据我所知)使用
typedef int Pair[2];
确保它正确对齐(没有尾随垃圾字节等)。如果我想根据第一个元素对对进行排序,我可以这样做:
#include <iostream>
#include <algorithm>
typedef int Pair[2];
int compare(Pair n1, Pair n2) { return n1[0] < n2[0]; }
int main() {
int N=5;
int data[10] = {1,2, 7,8, 13,14, 4,5, 10,11};
Pair *pairs = (Pair *)((void *)data);
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
std::sort(data, data+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
return 0;
}
我可以将错误消息汇总为错误:数组必须使用大括号括起初始化程序进行初始化,请参阅下面的完整消息。它是由std :: sort调用引起的。
我将Pair typedef包装在一个联合中(http://ideone.com/TVmEeZ),这似乎有效。 为什么c ++(或std :: sort)没有以与union类似的方式看到int [2]?
完成编译器输出:
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘void std::__insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2250:70: required from ‘void std::__final_insertion_sort(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5514:55: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2186:11: error: array must be initialized with a brace-enclosed initializer
__val = _GLIBCXX_MOVE(*__i);
^
In file included from /usr/include/c++/4.8/algorithm:62:0,
from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_algo.h:2188:17: error: invalid array assignment
*__first = _GLIBCXX_MOVE(__val);
^
/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of ‘_RandomAccessIterator std::__unguarded_partition(_RandomAccessIterator, _RandomAccessIterator, const _Tp&, _Compare) [with _RandomAccessIterator = int (*)[2]; _Tp = int [2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:2319:78: required from ‘_RandomAccessIterator std::__unguarded_partition_pivot(_RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2360:62: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_algo.h:2287:35: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
while (__comp(*__first, __pivot))
^
/usr/include/c++/4.8/bits/stl_algo.h:2290:34: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]
while (__comp(__pivot, *__last))
^
In file included from /usr/include/c++/4.8/bits/stl_pair.h:59:0,
from /usr/include/c++/4.8/bits/stl_algobase.h:64,
from /usr/include/c++/4.8/bits/char_traits.h:39,
from /usr/include/c++/4.8/ios:40,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from prog.cpp:1:
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::make_heap(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1970:47: required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59: required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_heap.h:446:25: error: array must be initialized with a brace-enclosed initializer
_ValueType __value = _GLIBCXX_MOVE(*(__first + __parent));
^
/usr/include/c++/4.8/bits/stl_heap.h: In instantiation of ‘void std::__pop_heap(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’:
/usr/include/c++/4.8/bits/stl_algo.h:1973:50: required from ‘void std::__heap_select(_RandomAccessIterator, _RandomAccessIterator, _RandomAccessIterator, _Compare) [with _RandomAccessIterator = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5363:59: required from ‘void std::partial_sort(_RAIter, _RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:2355:68: required from ‘void std::__introsort_loop(_RandomAccessIterator, _RandomAccessIterator, _Size, _Compare) [with _RandomAccessIterator = int (*)[2]; _Size = int; _Compare = bool (*)(int*, int*)]’
/usr/include/c++/4.8/bits/stl_algo.h:5513:44: required from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = int (*)[2]; _Compare = bool (*)(int*, int*)]’
prog.cpp:16:35: required from here
/usr/include/c++/4.8/bits/stl_heap.h:339:28: error: array must be initialized with a brace-enclosed initializer
_ValueType __value = _GLIBCXX_MOVE(*__result);
^
In file included from /usr/include/c++/4.8/bits/stl_algo.h:61:0,
from /usr/include/c++/4.8/algorithm:62,
from prog.cpp:2:
/usr/include/c++/4.8/bits/stl_heap.h:340:17: error: invalid array assignment
*__result = _GLIBCXX_MOVE(*__first);
^
答案 0 :(得分:1)
std::sort(data, data+N, compare);
您正在排序data
,而不是pairs
。也就是说,您的新方法仍然是未定义的行为,因此无法保证工作 1 。你基本上是想把一个方形钉固定在一个圆孔里。如果要使用std::sort
,则显示有效数据 - 这意味着在您的情况下进行复制,或者编写自定义迭代器,将数组视为连续对的集合。
1 这是一种轻率的轻描淡写。 - 不要这样做。
答案 1 :(得分:-1)
为int
交换两个std::pair<int,int>
的数组为我做了伎俩(live at ideone):
#include <iostream>
#include <algorithm>
#include <memory>
typedef std::pair<int,int> Pair;
bool compare(const Pair& i, const Pair& j) { return i.first < j.first; }
int main() {
const int N=5;
Pair pairs[N] = {{1,2}, {7,8}, {13,14}, {4,5}, {10,11}};
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;
std::sort(pairs, pairs+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i].first << ", " << pairs[i].second << ")" << std::endl;
}
另一种方法是在结构中封装两个int
的数组。您的代码中的问题是std::sort
需要一个可比较的数组(您使用compare
函数修复它)和 copy-or-move-assignable 项(数组都不是)
使用std::array
:
#include <iostream>
#include <algorithm>
#include <memory>
typedef std::array<int, 2> Pair;
bool compare(const Pair& i, const Pair& j) { return i[0] < j[0]; }
int main() {
const int N=5;
Pair pairs[N] = {1,2, 7,8, 13,14, 4,5, 10,11};
std::cout << "unsorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
std::sort(pairs, pairs+N, compare);
std::cout << "sorted" << std::endl;
for(int i=0; i<N;++i) std::cout << i << ": (" << pairs[i][0] << ", " << pairs[i][1] << ")" << std::endl;
}