在学习C++11时,我对移动对象的行为方式感到惊讶。考虑以下代码:
#include <exception>
#include <iostream>
#include <type_traits>
class Moveable {
public:
Moveable() {
std::cout << "Acquire odd resource\n";
}
~Moveable() noexcept(false) {
std::cout << "Release odd resource\n";
// if (!std::uncaught_exception() && error_during_release) {
// throw std::exception("error");
// }
}
Moveable(Moveable const &) = delete;
Moveable &operator=(Moveable const &) = delete;
Moveable(Moveable &&) = default;
Moveable &operator=(Moveable &&) = default;
};
int main(int argc, char *argv[]) {
static_assert(!std::is_copy_constructible<Moveable>::value,
"is not copy constructible");
static_assert(!std::is_copy_assignable<Moveable>::value, "is not copy assignable");
static_assert(std::is_move_constructible<Moveable>::value, "is move constructible");
static_assert(std::is_move_assignable<Moveable>::value, "is move assignable");
Moveable moveable{};
Moveable moved{std::move(moveable)};
Moveable moved_again{std::move(moved)};
}
它产生以下输出:
$ clang++ --version
clang version 3.8.0 (tags/RELEASE_380/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/clang+llvm-3.8.0-x86_64-linux-gnu-ubuntu-14.04/bin
$ clang++ --std=c++14 --stdlib=libc++ -Wall -Werror -o move_and_destroy move_and_destroy.cc && ./move_and_destroy
Acquire odd resource
Release odd resource
Release odd resource
Release odd resource
我很惊讶,因为我希望创建一个可移动的 RAII类型。然而,似乎每个移动的中间件都被销毁了!有没有一种变化可以让我在“对象的生命周期”结束时释放资源?(也就是,在移动对象序列的生命周期结束时)在类似情况下,应该使用
std::unique_ptr
并完成。但是,在这种情况下,可能会出现〜Moveable()
抛出异常,显然std::unique_ptr
的析构函数将终止异常程序(至少在clang 3.8.0中如此)。
std::unique_ptr
内部检查了空指针,如果为空则不会释放资源以避免此问题。 - milleniumbug