直接上例子,更能清楚的显示区别: (例子参考自c++ primer 5th 课后题) 例子1:
#include<iostream>
#include<vector>
using namespace std;
struct X {
X() { std::cout << "X()" << std::endl; }
X(const X&) { std::cout << "X(const X&)" << std::endl; }
X& operator= (const X& x);
~ X() { std::cout << "~X()" << std::endl; }
};
X& X::operator=(const X& x)
{
std::cout << "=X()" << std::endl;
}
void f (X& x1, X* x2)
{
vector<X> xvec;
xvec.push_back(x1);
xvec.push_back(*x2);
cout << "------- destructor in f -----" << endl;
}
int main(){
cout << "------- constructor -----" << endl;
X x1;
X *x2 = new X();
cout << "------- copy constructor -----" << endl;
f (x1, x2);
cout << "------- destructor 1-----" << endl;
delete x2;
cout << "------- destructor 2-----" << endl;
return 0;
}
运行结果: 这里有个STL的知识点,为什么会在------- copy constructor -----之后会再拷贝一次和析构一次,因为vector容器一开始给的capable_size是1,当你push_back第二的对象时,就要重新开辟空间(一般来说是按照两倍空间扩容为2),把原来的东西拷贝过去,然后析构原来的空间,所以这里多调用了一次拷贝和析构。对应的你要push_back第三个时就会再次扩容(再次两倍空间扩容为4),大家可以自己试试,这里就不再展示。
------- constructor ----- X() X() ------- copy constructor ----- X(const X&) X(const X&) X(const X&) ~X() ------- destructor in f ----- ~X() ~X() ------- destructor 1----- ~X() ------- destructor 2----- ~X()
例子2:
#include<iostream>
using namespace std;
class HasPtr {
friend void swap(HasPtr&, HasPtr&);
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0){}
HasPtr(const HasPtr& hp) : ps (new std::string(*hp.ps)), i (hp.i) {}
HasPtr& operator= (const HasPtr& hp)
{
auto newp = new std::string(*hp.ps);
delete ps;
ps = newp;
i = hp.i;
return *this;
}
std::string& getPs()
{
return *ps;
}
~HasPtr () { delete ps; }
private:
std::string *ps;
int i;
};
inline void swap(HasPtr& lhs, HasPtr& rhs)
{
using std::swap;
swap (lhs.ps, rhs.ps);
swap (lhs.i, rhs.i);
std::cout << "call the swap function." << std::endl;
}
int main()
{
HasPtr hp1 ("hello");
HasPtr hp2 ("world");
swap(hp1, hp2);
cout << hp1.getPs() << endl;
cout << hp2.getPs() << endl;
return 0;
}
运行结果:
call the swap function. world hello
例子3:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class HasPtr {
friend void swap(HasPtr&, HasPtr&);
friend bool operator< (HasPtr& lhs, HasPtr& rhs);
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0){}
HasPtr(const HasPtr& hp) : ps (new std::string(*hp.ps)), i (hp.i) {}
HasPtr& operator= (HasPtr hp)
{
this->swap(hp);
std::cout << "call operator=(HasPtr &rhs)" << std::endl;
return *this;
}
void swap(HasPtr &rhs)
{
using std::swap;
swap(ps, rhs.ps);
swap(i, rhs.i);
std::cout << "call swap(HasPtr &rhs)" << std::endl;
}
std::string& getPs()
{
return *ps;
}
~HasPtr () { delete ps; }
private:
std::string *ps;
int i;
};
void swap(HasPtr& lhs, HasPtr& rhs)
{
lhs.swap(rhs);
}
bool operator< (HasPtr& lhs, HasPtr& rhs)
{
std::cout << lhs.getPs() <<" "<<rhs.getPs()<<" "<<(*lhs.ps < *rhs.ps)<<endl;;
return *lhs.ps < *rhs.ps;
}
int main()
{
HasPtr hp1 ("Anna");
HasPtr hp2 ("hello");
HasPtr hp3 ("world");
vector<HasPtr> hvec;
hvec.push_back(hp1);
hvec.push_back(hp2);
hvec.push_back(hp3);
std::sort (hvec.begin(), hvec.end());
for (auto i : hvec) {
cout << i.getPs() << endl;
}
return 0;
}
运行结果: 具体底层是怎么实现的有知晓的小伙伴可以评论区补充一下。
hello Anna 0 hello Anna 0 call swap(HasPtr &rhs) call operator=(HasPtr &rhs) world Anna 0 world hello 0 call swap(HasPtr &rhs) call operator=(HasPtr &rhs) Anna hello world
例子4:
#include <iostream>
class HasPtr {
friend void swap(HasPtr&, HasPtr&);
friend bool operator< (HasPtr& lhs, HasPtr& rhs);
public:
HasPtr(const std::string &s = std::string()) : ps(new std::string(s)), i(0){}
HasPtr(const HasPtr& hp) : ps (new std::string(*hp.ps)), i (hp.i) {}
HasPtr& operator= (HasPtr hp)
{
this->swap(hp);
std::cout << "call operator=(HasPtr &rhs)" << std::endl;
return *this;
}
HasPtr (HasPtr&& hp) noexcept;
void swap(HasPtr &rhs)
{
using std::swap;
swap(ps, rhs.ps);
swap(i, rhs.i);
std::cout << "call swap(HasPtr &rhs)" << std::endl;
}
std::string& getPs()
{
return *ps;
}
~HasPtr () { delete ps; }
private:
std::string *ps;
int i;
};
void swap(HasPtr& lhs, HasPtr& rhs)
{
lhs.swap(rhs);
}
using namespace std;
HasPtr::HasPtr(HasPtr&& hp) noexcept : ps (hp.ps), i (hp.i)
{
hp.ps = nullptr;
cout << "call move constructor." << endl;
}
int main()
{
HasPtr hp1("hello"), hp2("world");
hp1 = std::move (hp2);
cout << hp1.getPs() << endl;
return 0;
}
运行结果:
call move constructor. call swap(HasPtr &rhs) call operator=(HasPtr &rhs) world
|