如何用std::sort对指针指向的值排序?原尝试为何无效?
嘿,我来帮你搞清楚这个问题的来龙去脉,以及怎么解决它~
问题出在哪?
首先你得明白一个核心点:std::sort操作的是容器里的元素本身,而不是元素指向的内容。
你的初始代码里,容器存的是int*指针,sort做的只是把这些指针的地址在vector里重新排列——就像把几个指向不同盒子的标签重新排序,但盒子里的东西(原变量a、b、c的值)根本没碰,所以原变量自然不会变。
后来你尝试自定义assignement_pointer重载赋值运算符,但没用,是因为C++11之后std::sort优先使用移动语义(move)和swap操作来交换元素,而不是你重载的赋值运算符。你的包装类本质上还是在交换指针地址,原变量的值当然纹丝不动。
怎么实现“原变量跟着排序”?
你的需求本质是:排序指针的同时,让指针指向的原变量的值也变成有序的。这里有两种靠谱的思路:
思路1:直接排序值,写回原变量(简单直接)
如果不需要纠结“通过指针向量排序”这个形式,最省事的办法就是先把原变量的值取出来排序,再写回去,最后更新指针向量:
#include <iostream> #include <vector> #include <algorithm> int main() { int a = 3; int b = 2; int c = 1; // 1. 收集所有值并排序 std::vector<int> sorted_values{a, b, c}; std::sort(sorted_values.begin(), sorted_values.end()); // 2. 把排序后的值写回原变量 a = sorted_values[0]; b = sorted_values[1]; c = sorted_values[2]; // 3. 更新指针向量(或者重新创建) std::vector<int*> vec{&a, &b, &c}; std::cout << "vec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n'; std::cout << "abc = " << a << ", " << b << ", " << c << '\n'; }
运行后原变量和指针指向的内容都会是有序的。
思路2:自定义指针包装类,让swap交换值而非指针
如果你一定要通过指针向量的排序过程来触发原变量的交换,可以自定义一个包装类,重载swap操作——因为std::sort在交换元素时会调用swap,我们让它交换指针指向的原变量值,而不是指针本身:
#include <iostream> #include <vector> #include <algorithm> #include <utility> class ValueSwapPtr { private: int* ptr; public: explicit ValueSwapPtr(int* p) : ptr(p) {} // 重载解引用,方便获取值 int& operator*() const { return *ptr; } int* get() const { return ptr; } // 核心:自定义swap,交换指向的原变量值 friend void swap(ValueSwapPtr& lhs, ValueSwapPtr& rhs) { std::swap(*lhs.ptr, *rhs.ptr); } // 移动构造/赋值和拷贝赋值,都通过swap实现 ValueSwapPtr(ValueSwapPtr&& other) noexcept : ptr(nullptr) { swap(*this, other); } ValueSwapPtr& operator=(ValueSwapPtr other) { swap(*this, other); return *this; } }; // 排序用的比较函数,基于指向的值 bool compare(const ValueSwapPtr& a, const ValueSwapPtr& b) { return *a < *b; } int main() { int a = 3; int b = 2; int c = 1; std::vector<ValueSwapPtr> vec{&a, &b, &c}; std::sort(vec.begin(), vec.end(), compare); std::cout << "vec = " << *vec[0] << ", " << *vec[1] << ", " << *vec[2] << '\n'; std::cout << "abc = " << a << ", " << b << ", " << c << '\n'; }
这个代码运行后,原变量a、b、c的值会被交换成1、2、3,vector里的包装类指向的内容也会是有序的——因为sort每次交换元素时,都会触发我们自定义的swap,交换原变量的值。
最后总结
- 原生指针排序只会动指针地址,碰不到原变量,这是
std::sort的设计逻辑——它只操作容器内的元素。 - 之前的包装类失效是因为
sort用了move/swap而非赋值运算符,没触发你写的逻辑。 - 两种解决方案选哪个看你的需求:追求简单就用思路1,一定要通过指针排序触发交换就用思路2。
内容的提问来源于stack exchange,提问作者Stack Danny
相关产品推荐
相关产品推荐

