I have defined a class "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;
};
This is my 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;
}
bool operator<(const HasPtr obj) const
as const?
I think all elements in the vector aren't const. Right?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
=====================================
Why there are so many "copy construction" and "assignment"?
I have been told that when the vector's element number is small, it uses a different algorithm but not swap.
The default constructor HasPtr() and the String constructor HasPtr(const std::string &s = std::string()) are not ambiguous. I don't know why.
Thanks
About the const
qualifier of operator<()
:
Imagine you have this function
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;
}
If your HasPtr::operator<()
was declared as
bool operator<(const HasPtr &obj) // <-- without const here
{ /* ... */ }
then the call a<b
in the previous my_fnct()
would
not be allowed by the compiler since the parameter a
is
declared as const
but the operator<()
does not promise
in its prototype that a
will not be modified..
On the other hand, if your HasPtr::operator<()
is declared as
bool operator<(const HasPtr &obj) const // <-- const at the end here
{ /* ... */ }
then the call a<b
in the previous my_fnct()
will be allowed by
the compiler since the const
keyword at the end of the prototype
ensures that the left operand of the comparison (a
in my previous
example) will not be modified.