条款25:考虑写一个不抛出异常的swap函数

本文探讨了如何在C++中考虑编写一个不抛出异常的swap函数,通过重载标准库的swap模板函数,以提高代码的健壮性和效率。

我们可以调用std下的swap函数,这是一个模板函数:既可以:

	int a = 1;
	int b = 2;
	std::swap(a,b);
	cout<<"a = "<<a<<" b = "<<b<<endl;

也可以(前提这个类型支持复制构造函数和赋值构造函数):

class Test
{
public:
	Test(int i):val(i){}
	int getVal(){return val;}
private:
	int val;
};

	Test a(1);
	Test b(2);
	std::swap(a,b);
	cout<<"a = "<<a.getVal()<<" b = "<<b.getVal()<<endl;
	return 0;
这个函数是是同通过类似int tmp = a; a = b; b = tmp的方法实现的,所以,如果类中的数据成员较多,这样的交换缺乏效率。
相比之下,“以指针指向一个对象,内含真正的数据”的方法更受欢迎。比如pimpl(pointer to implementation)。然后交换它们的指针。按照这种方法,我们应该这样设计我们的类:

//类的具体实现
class TestImpl
{
public:
	TestImpl(int i):ival(i){}
	int getVal(){return ival;}
	
private:
	int ival;
};

//指针
class Test
{
public:
	Test(int i):p(new TestImpl(i)){}
	~Test(){delete p;}
	Test operator=(const Test rhs)
	{
		*p = *(rhs.p
<think>好的,我现在需要回答用户关于C++中内置swap函数的使用方法和示例的问题。首先,我得确认用户的问题是什么。他们提到了引用中的swap函数在map中的应用以及Effective C++中的建议,想知道C++是否有内置的swap函数以及如何使用。 首先,我应该回忆C++标准库中的swap函数是否存在。C++标准库确实在<algorithm>和<utility>头文件中提供了swap函数过,根据C++版本的同,可能位置有变化。在C++11之后,更推荐使用<utility>中的swap,而<algorithm>中的可能被保留但逐渐淘汰。需要确认这一点是否正确。 接下来,用户需要使用方法和示例。对于内置类型,比如int、double,swap可以直接使用,比如swap(a, b);。对于容器类,比如vector、map,同样可以直接使用,因为标准库已经为这些类型特化了swap,使其高效交换内部数据指针,而是逐个元素交换。这点需要强调,说明效率高。 然后,用户可能想知道自定义类型如何处理swap。这里应该提到,如果自定义类型没有定义自己的swap函数,std::swap会使用默认的拷贝构造函数和赋值操作符,这可能导致效率低下。因此,建议为自定义类提供特化的swap函数,或者在类内部定义swap方法,并通过ADL(参数依赖查找)来优化。这可能需要引用Effective C++中的条款,比如条款25提到的编异常swap函数。 然后,关于示例代码。应该包括内置类型的例子、标准容器的例子,以及自定义类型的例子。比如,交换两个整数,交换两个vector,交换两个map,以及自定义类的swap实现。需要注意的是,在自定义类中,应该如何重载swap函数,是否要特化std::swap或者提供友元函数等。根据Effective C++的建议,最好在类所在的命名空间内定义swap函数,而是直接特化std模板,除非是对于类模板的情况可能需要部分特化,但C++允许部分特化函数,所以可能需要重载。 另外,要注意swap的使用方法是否正确,是否需要引入std命名空间,或者使用using std::swap;来启用ADL,这样才能正确调用用户定义的swap函数。例如: using std::swap; swap(obj1, obj2); 这样,如果obj1和obj2是自定义类型,并且在其命名空间中有定义swap,则会优先调用该swap,否则使用std::swap。这样可以提高效率和灵活性。 关于示例代码的正确性,要确保语法正确,比如使用正确的头文件,正确的命名空间,以及正确的函数调用方式。例如,std::swap在C++11之后在<utility>中,而之前可能在<algorithm>中。因此,建议包含<utility>并使用std命名空间。 可能还需要提到移动语义(C++11引入)对swap的影响,因为交换指针或资源句柄更为高效,而移动语义允许更高效的资源管理。但用户的问题可能需要深入到这里,过可以简要提及。 最后,总结swap函数的使用场景,强调标准库提供的swap已经足够高效,对于自定义类型需要自行优化,并参考Effective C++的建议来设计。同时,确保示例代码覆盖同情况,并正确展示如何使用。 现在需要组织这些信息,结构清晰,分点说明使用方法,给出示例,并回答相关问题。同时注意引用中的内容,引用[1]提到map的swap函数,引用[2]提到Effective C++的swap实现建议,需要适当引用这些内容。</think>C++标准库中提供了内置的`std::swap`函数,用于交换两个对象的值。以下是具体使用方法和示例: --- ### **1. `std::swap`的基本用法** - **头文件**:需包含`<utility>`(C++11起)或`<algorithm>`(旧版本兼容)。 - **语法**:`std::swap(a, b);` - **作用**:将对象`a`和`b`的值互换。 #### **示例:交换内置类型** ```cpp #include <iostream> #include <utility> // 包含swap函数 int main() { int x = 10, y = 20; std::swap(x, y); std::cout << "x=" << x << ", y=" << y; // 输出:x=20, y=10 return 0; } ``` --- ### **2. 交换标准容器** 标准库容器(如`vector`、`map`)已针对`swap`进行优化,时间复杂度为$O(1)$,仅交换内部指针而非元素[^1]。 #### **示例:交换`std::map`** ```cpp #include <map> #include <utility> int main() { std::map<int, std::string> m1{{1, "apple"}, {2, "banana"}}; std::map<int, std::string> m2{{3, "cherry"}}; std::swap(m1, m2); // 交换m1和m2的内容 // m1变为{{3, "cherry"}}, m2变为{{1, "apple"}, {2, "banana"}} return 0; } ``` --- ### **3. 自定义类型的`swap`优化** 默认`std::swap`通过三次拷贝交换对象,可能效率低下。**优化方法**: - 为自定义类定义专用的`swap`函数,并特化`std::swap`或通过ADL(参数依赖查找)调用。 #### **示例:自定义类的`swap`** ```cpp #include <algorithm> class MyClass { public: int* data; MyClass(int size) { data = new int[size]; } ~MyClass() { delete[] data; } // 定义成员swap函数 void swap(MyClass& other) noexcept { std::swap(data, other.data); // 仅交换指针 } }; // 特化std::swap namespace std { template<> void swap<MyClass>(MyClass& a, MyClass& b) noexcept { a.swap(b); } } // 使用示例 int main() { MyClass obj1(10), obj2(20); std::swap(obj1, obj2); // 高效交换内部指针 return 0; } ``` > **注意**:根据Effective C++条款25,优先在类所在命名空间定义`swap`而非特化`std::swap`[^2]。 --- ### **4. 通过ADL调用自定义`swap`** ```cpp namespace MyNamespace { class MyClass { /* ... */ }; void swap(MyClass& a, MyClass& b) { a.swap(b); } } int main() { MyNamespace::MyClass a, b; using std::swap; // 启用ADL swap(a, b); // 优先调用MyNamespace::swap return 0; } ``` --- ### **
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值