我正在尝试了解重载方法,特别是关于bool operator()。 请尝试理解。我确实试过阅读一些关于重载运算符的文章,但仍然无法得到它; /
我有来自STL的set容器,它按字母顺序自动对其''对象'进行排序,但是我想修改它以便它根据它们的长度对字符串进行排序。
这是我难以理解的工作代码
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
struct MyOrder
{
bool operator()(const string &first, const string &second)
{
int length1 = first.length(); //** assigning length of strings (arguments)
//** to int, so that we will compare their lengths
int length2 = second.length(); //** same story**//
if(length1 == length2) //** if both strings are the same length, code will return
//** true, but what does is mean first < second ?, will it
swap places of arguments or what ?
return (first < second);
return (length1 < length2); //** same story, if they are not the same length, than
//** what ? return true, and swap arguments' places ?
}
}
int main(void)
{
set<string, Myorder> names;
names.insert("Tony Soprano");
names.insert("Christopher Moltisanti");
set<string>::iterator it;
for(it = names.begin(); it != names.end(); ++it)
{
cout << *it << endl;
}
}
答案 0 :(得分:1)
set<>
的第二个模板参数(如果提供)是一个运算符,用于确定您希望元素的排序方式。默认运算符是使用std::less<>
的结果,如果第一个参数小于第二个参数,则返回true。使用默认比较运算符时,将对组中的元素 e 0 .. e N 进行排序,以便 e i &lt; e i + 1 为真。
()
的运算符重载允许调用MyOrder
的实例,就好像它是一个函数一样。通过提供MyOrder
作为第二个模板参数,您要更改集合中元素的顺序,以便order
是MyOrder
的实例,order(
< em> e i , e i + 1 )
为真。
MyOrder
的实施方式如下:
如果两个参数的长度相等,则返回first < second
的结果
- 这意味着如果字符串长度相等,如果第一个字符串按字母顺序小于第二个字符串则返回true,否则返回false。
如果两个参数的长度不相等,则first
短于second
时返回true,否则返回false。
set<>
如何维护元素的排序是一个实现细节,但是在添加新元素时它会这样做。最初,当没有元素时,添加第一个元素没有限制。在添加每个新元素时,添加它就好像已使用提供的运算符与所有现有元素进行比较,以确定其正确的相对位置。
因此,如果该集合包含{ "m", "zz", "aaa" }
,并且您想要向其添加"ii"
,那么它将放在"m"
之后(因为它比它长),但在{{{}之前1}}(因为它按字母顺序小于它)。结果将变为"zz"
。
答案 1 :(得分:1)
<
运算符表示小于,它的计算结果为true
或false
。例如:
3 < 4 // true
6 < 5 // false
7 < 7 // false
它不会“交换参数”或任何东西。
当应用于std::string
等类类型时,<
等运算符会调用该类的重载operator<
函数。对于std::string
,它使该运算符重载以进行词典比较,即字典顺序。例如:
string("computer") < string("dog") // true
string("a") < string("abc") // true
要理解的另一件事是std::sort
(以及其他标准容器的排序)如何使用operator<
。规则是:
a < b
,则表示排序顺序中的a
早于b
a
要晚于b
,要么a
和b
在排序顺序中相同。如果需要区分最后两种情况(即a
是否晚于b
,或者它们是否相等),则可以检查b < a
。如果a < b && b < a
意味着它们是平等的。
不要担心正在使用哪种排序算法,或者它是如何做的。您的代码只需要确保其operator<
函数返回false
或true
,如上所述。排序算法将使用该信息来生成排序结果。
所以,回到你在代码中看到的那一行:
if(length1 == length2)
return (first < second);
return length1 < length2;
这意味着:
因此,如果该集合为dog car cheese boat dog
,则排序顺序为car dog dog boat cheese
。
答案 2 :(得分:1)
评论区域中的问题表明您希望MyOrder::operator()
交换实际元素。这不是真的。您的MyOrder仿函数用于比较std::set
内部的值,您不需要知道。通过这种方式,您可以抽象std::set
的实施细节,并以MyOrder
仿函数的形式提供您的排序标准。因此,您可以使用相同的仿函数,例如std::sort
:
int main(void)
{
std::vector< std::string> names;
names.push_back("Tony Soprano");
names.push_back("Christopher Moltisanti");
std::sort( names.begin(), names.end(), MyOrder() );
std::vector<std::string>::iterator it;
for( it = names.begin(); it != names.end(); ++it)
{
std::cout << *it << std::endl;
}
}
并且不需要知道std::sort
如何移动元素。
答案 3 :(得分:-1)
operator()
的运算符重载使您的类MyOrder
的实例可以被调用,就好像它是一个函数一样。具有operator()
的班级也称为仿函数。 ()
是应用程序运算符。
您可以通过这种方式将自定义排序标准应用于算法 - std::sort
将在您的班级MyOrder::operator()( std::string, std::string)
的实例上使用对MyOrder
的调用来询问如何处理这两个字符串。
现在我们将根据长度进行排序,并在长度相等的情况下使用字母顺序。
#include <iostream>
#include <set>
#include <iterator>
struct MyOrder
{
bool operator()( const std::string &first, const std::string &second)
{
size_t length1 = first.length();
size_t length2 = second.length();
if ( length1 == length2) return first < second;
return ( length1 < length2);
}
};
其余的一样(有一些纠错,MyOrder而不是Myorder)
int main(void)
{
std::set< std::string, MyOrder> names;
names.insert("Tony Soprano");
names.insert("Christopher Moltisanti");
std::set<std::string>::iterator it;
for( it = names.begin(); it != names.end(); ++it)
{
std::cout << *it << std::endl;
}
}