我确实理解为什么有时建议为swap()给定的类实现我们自己的函数。
例如,如果我们有一个遵循pimpl习惯用法的类,我们可能希望定义自己的复制构造函数,以便它执行作为参数传递的对象内容的深层复制,而不是由默认的复制构造函数。这同样适用于复制赋值运算符。
因为它似乎是通过复制构造函数和复制赋值std::swap()运算符(至少在 C++03 中)实现的。对要交换的对象执行深拷贝是低效的,因为只需要交换这些对象所包含的指针。
我的问题是为什么我们应该将我们的swap()函数实现为非抛出函数。
在上面解释的情况下,我认为这只是关于语义:因为没有分配新资源(即:只是交换两个现有指针)。对于这样一种函数来说,抛出异常没有多大意义。
然而,在这个推理中我可能忽略了其他原因或场景。
我的问题是为什么我们应该将我们的
swap()函数实现为非抛出函数
因为swap如果它可能抛出,那就完全没用了。
考虑一下:你有swap两个实例,并且操作会抛出异常。现在,他们处于什么状态?
强有力的保证是,如果抛出异常,不会产生任何副作用,这意味着两个原始对象都保持原始状态。
如果我们不能满足强有力的保证,那么在很多情况下我们根本无法使用swap,因为没有办法从故障中有效地恢复,并且根本没有必要编写该版本swap。
因为它没有理由抛出。
(现在)的简单实现swap使用移动分配和构造。
移动构造函数通常没有理由抛出异常:它不会分配任何新的东西,它只是重新安置现有的数据。一般来说,移动赋值没有理由抛出异常(如上所述),并且析构函数永远不应该抛出异常——而这些是唯一需要的操作。