[英]Why does vector comparison with < operator compare each item twice?
在這個例子中,比較兩個向量與<operator result in operator <,在Integer類上定義,為每個元素調用兩次。 但是,將兩個向量與==運算符進行比較時不會發生這種情況。
#include<iostream>
#include<vector>
class Integer {
public:
Integer(int value) : m_value(value) {}
friend bool operator<(const Integer& lhs, const Integer& rhs);
friend bool operator==(const Integer& lhs, const Integer& rhs);
private:
int m_value;
};
bool operator<(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << " < " << rhs.m_value << '\n';
return lhs.m_value < rhs.m_value;
}
bool operator==(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << " == " << rhs.m_value << '\n';
return lhs.m_value == rhs.m_value;
}
int main()
{
std::vector<Integer> ivec1 {1,2,3};
std::vector<Integer> ivec2 {1,2,3};
std::cout << (ivec1 < ivec2) << '\n';
std::cout << (ivec1 == ivec2) << std::endl;
return 0;
}
此代碼打印:
1 < 1
1 < 1
2 < 2
2 < 2
3 < 3
3 < 3
0
1 == 1
2 == 2
3 == 3
1
為什么會這樣?
如果a < b
返回false
,則它不會告訴您b < a
,並且您必須測試它。 那是因為std::vector
的逐元素排序對於一對元素a, b
可以有三個結果:
a < b
,矢量比較返回true
。 b < a
,向量比較返回false
。 所以它必須比較兩個方向。 通過向您的班級添加標識數據,您可以更清楚地看到這一點:
#include<iostream>
#include<vector>
class Integer {
public:
Integer(int value, char tag) : m_value(value), m_tag(tag) {}
friend bool operator<(const Integer& lhs, const Integer& rhs);
friend bool operator==(const Integer& lhs, const Integer& rhs);
private:
int m_value;
char m_tag;
};
bool operator<(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << ' ' << lhs.m_tag << " < " << rhs.m_value << ' ' << rhs.m_tag << '\n';
return lhs.m_value < rhs.m_value;
}
bool operator==(const Integer& lhs, const Integer& rhs) {
std::cout << lhs.m_value << ' ' << lhs.m_tag << " == " << rhs.m_value << ' ' << rhs.m_tag << '\n';
return lhs.m_value == rhs.m_value;
}
int main()
{
std::vector<Integer> ivec1 {{1, 'a'} ,{2, 'a'}, {3, 'a'}};
std::vector<Integer> ivec2 {{1, 'b'} ,{2, 'b'}, {3, 'b'}};
std::cout << (ivec1 < ivec2) << '\n';
std::cout << (ivec1 == ivec2) << std::endl;
return 0;
}
這會產生:
1 a < 1 b
1 b < 1 a
2 a < 2 b
2 b < 2 a
3 a < 3 b
3 b < 3 a
0
1 a == 1 b
2 a == 2 b
3 a == 3 b
1
為了找到ivec1
和ivec2
的字典順序,該實現尋找ivec1[i] < ivec2[i]
或ivec2[i] < ivec1[i]
的第一個索引i
,因為這將決定順序。
注意如果ivec1[i] < ivec2[i]
為假,這需要兩次比較。 特別地,上述情況留下兩種可能性,即“ ivec1[i]
和ivec2[i]
比較等價物”和“ ivec2[i] < ivec1[i]
”。 這個決定是需要進行第二次比較的地方。
一旦找到這樣的索引i
,實現就可以停止比較; 但由於所有條目都比較了您的示例中的等效項,因此必須對每對條目執行兩次比較。
這是因為C ++目前處理比較的設計存在缺陷。 他們正在用c ++ 2a修復它; 我不知道它是否會得到vector
,但基本問題將得到解決。
一,問題。
std::vector
的<
基於每個元素<
。 但是<
是一項糟糕的工具。
如果你有兩個元素a
和b
,要以字面順序排列元組a,b
你需要這樣做:
if (self.a < other.a)
return true;
if (other.a < self.a)
return false;
return self.b < other.b;
一般來說,這需要2N-1次調用<
如果你想要lexographicaly訂購N個元素的集合。
這已經知道了很長時間,這就是為什么strcmp
返回一個包含3種值的整數: -1
表示less, 0
表示相等, +1
表示更大(或者,通常,值小於,等於或大於比零)。
有了這個你可以做:
auto val = compare( self.a, other.a );
if (val != 0) return val;
return compare( self.b, other.b );
這需要最多N
調用來compare
集合中的每個元素。
現在,修復。
c ++ 2a添加了太空船比較運算符<=>
。 它返回一個可以比較大於或小於零的類型,其確切類型通告保證操作提供的內容。
這類似於C的strcmp
,但適用於支持它的任何類型。 此外,有std
函數使用<=>
如果可用),否則使用<
和==
等來模擬它。
假設向量的要求被重寫為使用<=>
,帶<=>
類型將避免雙重比較,並且每次最多只需<=>
'd,以便在調用<
時執行std::vector
的詞法排序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.