STL按客户“ <”运算符对向量排序。为什么要将'<'运算符定义为const?

时间:2019-10-08 06:19:24

标签: c++ operator-overloading swap

我定义了一个“ HasPtr”类:

#include <iostream>
#include <string>

class HasPtr {
public:
   HasPtr()
      : ps(new std::string()), i() {
      std::cout << "Default constructor execute" << std::endl;
   }
   HasPtr(const std::string &s, int a)
      : ps(new std::string(s)), i(a) {
      std::cout << "Sting with int constructor execute" << std::endl;
   }
   HasPtr(const std::string &s = std::string())
      : ps(new std::string(s)), i(std::stoi(s)) {
      std::cout << "String constructor execute" << std::endl;
   }
   HasPtr(const HasPtr &obj)
      : ps(new std::string(*obj.ps)), i(obj.i) {
      std::cout << "Copy constructor execute" << std::endl;
   }
   HasPtr & operator=(const HasPtr &rhs) {
      std::cout << "Assign execute" << std::endl;
      ps = new std::string(*rhs.ps);
      i = rhs.i;
      return *this;
   }
   ~HasPtr() {
      delete ps;
   }

   std::string get_str() const {
      return *ps;
   }

   int get_i() const {
      return i;
   }

   bool operator<(const HasPtr obj) const {
      std::cout << "Operator < execute" << std::endl;
      return i < obj.i;
   }

   friend void swap(HasPtr &lhs, HasPtr &rhs) {
      std::cout << "HasPtr::swap function execute" << std::endl;
      std::swap(lhs.ps, rhs.ps);
      std::swap(lhs.i, rhs.i);
   }

private:
   std::string *ps;
   int i;
};

这是我的main.cpp:

#include <iostream>
#include <vector>
#include <algorithm>
#include "HasPtr.h"

int main() {
   std::vector<HasPtr> v;
   v.push_back(std::to_string(10));
   v.push_back(std::to_string(5));
   v.push_back(std::to_string(7));
   v.push_back(std::to_string(3));
   v.push_back(std::to_string(2));
   v.push_back(std::to_string(9));

   std::cout << "==========List the elements==========" << std::endl;
   for (const auto &i : v) {
      std::cout << i.get_str() << " ";
   }
   std::cout << std::endl;
   std::cout << "=====================================" << std::endl;

   sort(v.begin(), v.end());

   std::cout << "==========List the elements==========" << std::endl;
   for (const auto &i : v) {
      std::cout << i.get_str() << " ";
   }
   std::cout << std::endl;
   std::cout << "=====================================" << std::endl;
}
  1. 我想知道为什么应该将bool operator<(const HasPtr obj) const定义为const? 我认为向量中的所有元素都不是const。对吧?
  2. 我不了解执行情况
String constructor execute
Copy constructor execute
String constructor execute
Copy constructor execute
Copy constructor execute
String constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
String constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
String constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
Copy constructor execute
String constructor execute
Copy constructor execute
==========List the elements==========
10 5 7 3 2 9
=====================================
Copy constructor execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Assign execute
Assign execute
Copy constructor execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Assign execute
Copy constructor execute
Operator < execute
Assign execute
Copy constructor execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Assign execute
Assign execute
Assign execute
Assign execute
Copy constructor execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Assign execute
Assign execute
Assign execute
Assign execute
Assign execute
Copy constructor execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Copy constructor execute
Operator < execute
Assign execute
Copy constructor execute
Operator < execute
Assign execute
==========List the elements==========
2 3 5 7 9 10
=====================================

为什么会有这么多的“副本结构”和“任务”?

  1. 为什么未调用swap函数?向量如何重新排列元素?

有人告诉我,向量的元素数较小时,它会使用不同的算法,但不会交换。

默认构造函数HasPtr()和String构造函数HasPtr(const std :: string&s = std :: string())不明确。我不知道为什么。

谢谢

2 个答案:

答案 0 :(得分:2)

比较运算符应该只进行比较,比较和修改毫无意义且有害。定义const可以确保不会发生任何不良情况。

vector需要复制构造函数的复制赋值运算符可用。如果前者不可用,它将检查move构造函数和move赋值运算符。

答案 1 :(得分:1)

关于const的{​​{1}}限定词:

想象一下您具有此功能

operator<()

如果您的int my_fnct(const HasPtr &a, const HasPtr &b) { int result=12; // ... do something ... if(a<b) // <--- the comparison is important { result+=100; // or whatever ... } // ... do something ... return result; } 被声明为

HasPtr::operator<()

然后上一个bool operator<(const HasPtr &obj) // <-- without const here { /* ... */ } 中的呼叫a<b将 编译器不允许,因为参数my_fnct()为 声明为a,但const并不承诺 在其原型中,operator<()不会被修改。.

另一方面,如果您的a被声明为

HasPtr::operator<()

然后,前一个bool operator<(const HasPtr &obj) const // <-- const at the end here { /* ... */ } 中的呼叫a<b将被允许 从原型末尾的my_fnct()关键字开始的编译器 确保比较的左操作数({{1 例如)将不会被修改。