C++ swap操作

本文介绍C++中swap操作的基本原理及其应用,包括如何为自定义类实现swap函数以简化赋值运算符,并讨论了使用STL提供的swap函数来提高代码效率的方法。

swap操作

我们常用的交换两个数据的操作是这样

void swap_int(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

主函数调用是这样的

    int a = 100, b = 200;
    swap_int(a, b);
    cout << "a is " << a << endl;
    cout << "b is " << b << endl;

程序输出

a is 200
b is 100

可见a和b交换了,stl为我们提供了swap函数,可以交换两个对象的数据。但大部分情况还是需要我们实现自己的swap函数,比如交换两个HasPtr对象


class HasPtr
{
public:
    HasPtr() = default;
    HasPtr(const string &str);
    ~HasPtr();
    HasPtr(const HasPtr &hp);
    HasPtr &operator=(const HasPtr &hp);
    friend ostream &operator<<(ostream &os, const HasPtr &);
    friend void swap(HasPtr &, HasPtr &);

private:
    string *m_str;
    int m_index;
    static int _curnum;
};

void swap(HasPtr &hptr1, HasPtr &hptr2)
{
    using std::swap;
    swap(hptr1.m_index, hptr2.m_index);
    swap(hptr1.m_str, hptr2.m_str);
}

我们在类的声明里添加了swap友元函数。然后利用了stl的swap函数完成了类内部成员的交换。交换后两个类的m_str指针指向交换了。
有了我们自己实现的swap函数,就可以简化之前的赋值运算符了。但是我们要注释掉原来版本实现的operator = ,实现新版本的

HasPtr &HasPtr::operator=(HasPtr hptr)
{
    // hptr是一个局部变量
    //交换后hptr.m_str指向this.m_str原来指向的内存
    swap(*this, hptr);
    // return返回*this后,hptr自动被回收
    return *this;
}

新版本的operator=参数为HasPtr类型,而不是引用类型,这样hptr是赋值运算符右侧变量的副本,而函数内部通过swap交换this和hptr的数据和成员,最后返回*this。随着函数返回,那么形参也就会自动销毁了,这么做的好处是代码简洁,并且不用考虑自赋值的情况。

总结

本文介绍了swap操作,合理利用swap,并为类实现swap操作,可以简化我们的操作。当我们要实现sort等排序操作,内部会用到交换逻辑,如果想实现定制化的swap就需要为类实现swap函数。
https://gitee.com/secondtonone1/cpplearn
想系统学习更多C++知识,可点击下方链接。
C++基础

<think>好的,用户想了解C++swap函数的用法和示例。首先,我需要回忆C++标准库中的swap函数。标准库中的std::swap是一个模板函数,位于<utility>头文件中,用于交换两个同类型对象的值。这个函数在C++11之后有移动语义的支持,提高了效率。 接下来,用户可能需要知道基本用法,比如如何交换基本数据类型、容器等。比如交换int、double,或者std::vector、std::string。这里可以举几个例子,比如交换两个整数,交换两个vector容器,这些例子能展示swap的高效性,特别是对于容器来说,交换指针而不是元素,时间复杂度是O(1)。 然后,用户可能关心自定义类型的swap。这时候需要说明如何为自定义类重载swap函数,或者提供特化版本。需要注意ADL(参数依赖查找),以及友元函数的使用,确保swap能在正确的作用域被调用。此外,移动语义的优化也很重要,可以避免不必要的拷贝。 还有,用户可能想知道在STL容器中的swap成员函数,比如std::vector::swap,这和std::swap的区别。需要指出成员函数swap可能有更高的效率,因为直接操作内部数据结构,而std::swap通用但可能依赖移动构造函数。 可能用户也会对性能优化感兴趣,比如使用swap来释放内存,比如通过和临时空容器交换来收缩容量。这时候可以举一个vector的例子,说明如何通过swap来减少内存占用。 另外,可能需要提到异常安全性和noexcept修饰符,特别是在C++11之后,移动操作通常标记为noexcept,这样swap在标准容器中更高效,比如std::vector的swap需要保证不抛出异常。 然后,检查是否有相关引用可以链接。根据用户提供的引用,引用[1]提到代理类,可能和swap的实现无关;引用[2]关于模板,std::swap正是模板函数的一个例子;引用[3]可能不相关。所以引用[2]可以用来支持std::swap作为模板的例子。 最后,生成相关问题需要考虑用户可能的后续疑问,比如自定义类型的swap实现,性能对比,异常处理,以及应用场景如内存管理。这样可以覆盖用户潜在的需求。</think>### C++swap函数的用法与示例 C++标准库中的$swap$函数用于交换两个对象的值,其核心实现基于移动语义或拷贝操作。根据不同的应用场景,$swap$函数在基础数据类型、容器类、自定义类中均有广泛使用。 --- #### 1. 基本用法(标准库模板函数) 通过$<utility>$头文件引入,支持任意类型的交换: ```cpp #include <utility> int a = 10, b = 20; std::swap(a, b); // 交换后 a=20, b=10 std::vector<int> v1{1,2,3}, v2{4,5}; std::swap(v1, v2); // 交换容器内容(时间复杂度O(1)) ``` **说明**:对于STL容器(如$std::vector$),交换操作仅交换内部指针,时间复杂度为$O(1)$[^2]。 --- #### 2. 自定义类型优化 为自定义类实现高效的$swap$函数: ```cpp class MyData { public: MyData(const std::string& s) : data(s) {} friend void swap(MyData& a, MyData& b) noexcept { using std::swap; swap(a.data, b.data); // 利用ADL规则调用最佳swap } private: std::string data; }; // 使用示例 MyData obj1("Hello"), obj2("World"); swap(obj1, obj2); // 调用自定义swap ``` **关键点**: - 通过友元函数实现,支持参数依赖查找(ADL) - 使用$noexcept$优化移动语义 --- #### 3. STL容器的swap成员函数 部分容器(如$std::vector$)提供专用成员函数: ```cpp std::vector<int> vecA{1,2}, vecB{3,4,5}; vecA.swap(vecB); // vecA容量变为3,vecB容量变为2 ``` **优势**:直接操作容器内部存储,避免模板实例化开销。 --- #### 4. 应用场景与技巧 - **内存释放**:通过交换清空容器内存 ```cpp std::vector<int> large_vec(1000000); std::vector<int>().swap(large_vec); // 强制释放内存 ``` - **异常安全**:在拷贝赋值运算符中实现强异常安全保证 ```cpp MyData& operator=(MyData other) { swap(*this, other); return *this; } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋风辰

感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值