C++交换操作

标准库中swap的缺点

如果一个类定义了自己的swap,那么算法将使用类自定义版本,否则算法将使用标准库定义的swap,标准库定义的swap在交换两个对象时需要进行一次拷贝和两次赋值,理论上这些内存分配都是不必要的,我们更希望swap交换指针,而不是分配对象的新副本。

template <class _Ty, class>
inline void swap(_Ty& _Left, _Ty& _Right) _NOEXCEPT_COND(is_nothrow_move_constructible_v<_Ty>&&
        is_nothrow_move_assignable_v<_Ty>) { // exchange values stored at _Left and _Right
    _Ty _Tmp = _STD move(_Left);
    _Left    = _STD move(_Right);
    _Right   = _STD move(_Tmp);
}
class Person
{
public:
    const char* name_;
    Person(const char* name) :name_(name) {
        std::cout << "call Person::Person(name)" << std::endl;
    };
    Person(const Person& person) {//拷贝构造函数
        std::cout << "call Person::Person(person)" << std::endl;
        name_ = person.name_;
    };
    Person& operator=(const Person& person) {//拷贝赋值运算符
        std::cout << "call Person::operator=" << std::endl;
        name_ = person.name_;
        return *this;
    }
};

 

int main()
{
    Person person1{ "xiao hong" };
    Person person2{ "xiao ming" };
    swap(person1,person2);
    system("pause");
}

一次拷贝和两次赋值:

call Person::Person(name)
call Person::Person(name)
call Person::Person(person)
call Person::operator=
call Person::operator=

编写我们自己的swap函数

当有多个重载模板对一个调用提供同样好的匹配时,应选择最特例化的版本,所以下面的代码中我们自定义的swap匹配程度会优于std中定义的版本。

void swap(Person& person1, Person& person2)
{
    cout<<"swap person"<<endl;
    swap(person1.name_, person2.name_);
}
 

int main()
{
    Person person1{ "xiao hong" };
    Person person2{ "xiao ming" };
    swap(person1,person2);
    cout << person1.name_ << endl;//xiao ming
    cout << person2.name_ << endl;//xiao hong
    system("pause");
}

在赋值运算符中使用swap

定义swap的类通常用swap来定义它们的赋值运算符,这些运算符使用了一种名为拷贝并交换的技术,这种技术将左侧运算对象与右侧运算对象的一个副本进行交换。

在这个版本的赋值运算符中,参数并不是引用,而是右侧运算对象的一个副本,然后我们调用swap交换参数和*this中的数据成员,在赋值运算符结束时,参数被销毁,释放掉了左侧运算对象中原来的内存(如果申请了的话)。

void swap(Person& person1, Person& person2)
{
    cout<<"swap person"<<endl;
    swap(person1.name_, person2.name_);
}
 
Person& Person::operator=(Person person) {
    swap(*this, person);
    return *this;
}

int main()
{
    Person person1{ "xiao hong" };
    Person person2{ "xiao ming" };
    person1 = person2;
    cout << person1.name_ << endl;//xiao ming
    cout << person2.name_ << endl;//xiao ming
    system("pause");
}
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容