以下代码:
std::vector<std::tuple<int&>> v;
int a = 5; v.emplace_back(a);
int b = 4; v.emplace_back(b);
int c = 3; v.emplace_back(c);
int d = 2; v.emplace_back(d);
int e = 1; v.emplace_back(e);
std::sort(std::begin(v), std::end(v));
使用gcc / libstdc ++编译vs clang / libc ++ binary会产生不同的结果。
对于gcc/libstdc++,一个元素被复制到所有其他引用。
5 4 3 2 1
5 5 5 5 5
首先我认为clang/libc++按预期行为 但它最多只能处理一个向量中的5个元素(因为小容器有一个特例)。
5 4 3 2 1
1 2 3 4 5
传递更多元素时,结果类似于gcc。
5 4 3 2 1 0
3 4 5 5 5 5
使用std::sort
对带引用的元组容器(即使用std::tie
进行排序,结构的子集)是否有效?
如果没有,我应该期待任何警告吗?
答案 0 :(得分:6)
使用
std::sort
对带引用的元组容器(即使用std::tie
进行排序,结构的子集)是否有效?如果没有,我应该期待任何警告吗?
不,不。 std::sort()
的类型要求之一是:
- 解除引用的
RandomIt
类型必须符合MoveAssignable
和MoveConstructible
的要求。
表达式t = rv
中需要MoveAssignable
:
t
的值等效与分配前rv
的值相同。
但std::tuple<int&>
不是MoveAssignable,因为int&
不是MoveAssignable。如果您只是:
int& ra = a;
int& rb = b;
ra = std::move(rb);
ra
的值不等于rb
的先前值。 ra
仍然引用到a
,它不会更改为引用b
- 实际更改的内容是a
的值。
由于我们的类型不符合std::sort()
的前提条件,因此std::sort()
调用的结果只是未定义的行为。
请注意,可以对std::vector<std::tuple<std::reference_wrapper<int>>>
进行排序,因为std::reference_wrapper
是MoveAssignable。
另请注意,这可能让人想起无法按照旧的Herb Sutter article对auto_ptr
的容器进行排序。