这是使用并行数组引入的复杂性的一个很好的例子。
如果您坚持将它们保留为并行数组,这是一种可能的方法。创建一个整数索引向量,初始化为 { 0, 1, 2, 3, etc }。每个整数代表数组中的一个位置。使用自定义比较函数对索引向量进行排序,该函数使用索引来引用 array1(数字)。完成后,您可以使用已排序的索引对 array1 和 array2(名称)重新排序。
也可以编写自己的排序算法,同时对额外的数组执行交换。
或者可以通过使用巧妙设计的代理来欺骗std::sort 对两个数组进行同时排序。我将证明这样的事情是可能的,尽管下面的代码可能被认为是一个简单的 hackish 概念证明。
使用设计巧妙的代理来欺骗 std::sort
#include <iostream>
#include <algorithm>
constexpr size_t SZ = 2;
int Numbers[SZ] = {5, 2};
std::string Names[SZ] = {"Jeremy", "Samantha"};
int tempNumber;
std::string tempName;
class aproxy {
public:
const size_t index = 0;
const bool isTemp = false;
aproxy(size_t i) : index(i) {}
aproxy() = delete;
aproxy(const aproxy& b) : isTemp(true)
{
tempName = Names[b.index];
tempNumber = Numbers[b.index];
}
void operator=(const aproxy& b) {
if(b.isTemp) {
Names[index] = tempName;
Numbers[index] = tempNumber;
} else {
Names[index] = Names[b.index];
Numbers[index] = Numbers[b.index];
}
}
bool operator<(const aproxy& other) {
return Numbers[index] < Numbers[other.index];
}
};
int main() {
aproxy toSort[SZ] = {0, 1};
std::sort(toSort, toSort+SZ);
for(int i=0; i<SZ; ++i) {
std::cout << "Numbers[" << i << "]=" << Numbers[i] << std::endl;
std::cout << "Names[" << i << "]=" << Names[i] << std::endl;
}
return 0;
}
...设计更巧妙的代理可以完全避免分配 SZ“代理”元素的需要。
使用“设计更巧妙”的代理来欺骗 std::sort
#include <iostream>
#include <algorithm>
class aproxy;
constexpr size_t SZ = 2;
int Numbers[SZ] = {5, 2};
std::string Names[SZ] = {"Jeremy", "Samantha"};
aproxy *tempProxyPtr = nullptr;
int tempNumber;
std::string tempName;
class aproxy {
public:
size_t index() const
{
return (this - reinterpret_cast<aproxy*>(Numbers));
}
bool isTemp() const
{
return (this == tempProxyPtr);
}
~aproxy()
{
if(isTemp()) tempProxyPtr = nullptr;
}
aproxy() {}
aproxy(const aproxy& b)
{
tempProxyPtr = this;
tempName = Names[b.index()];
tempNumber = Numbers[b.index()];
}
void operator=(const aproxy& b) {
if(b.isTemp()) {
Names[index()] = tempName;
Numbers[index()] = tempNumber;
} else {
Names[index()] = Names[b.index()];
Numbers[index()] = Numbers[b.index()];
}
}
bool operator<(const aproxy& other) {
return Numbers[index()] < Numbers[other.index()];
}
};
int main() {
aproxy* toSort = reinterpret_cast<aproxy*>(Numbers);
std::sort(toSort, toSort+SZ);
for(int i=0; i<SZ; ++i) {
std::cout << "Numbers[" << i << "]=" << Numbers[i] << std::endl;
std::cout << "Names[" << i << "]=" << Names[i] << std::endl;
}
return 0;
}
免责声明: 虽然我上面的最后一个示例在技术上可能违反了严格别名规则(由于两种不同类型访问内存中的相同空间),但底层内存仅用于寻址空间 - 未修改 - 当我测试它时它似乎工作正常。此外,它完全依赖于std::sort 以某种方式编写:使用通过复制构造、单线程等初始化的单个临时变量。将所有这些假设放在一起,这可能是一个方便的技巧,但不是很便携,所以在你的时候使用风险自负。