1. 移动构造标记noexcept
时才会被正确调用
#include <iostream>
#include <string>
#include <vector>class Vehicle{
public:Vehicle(){std::cout << "Vehicle default-ctor called.\n";}Vehicle(const std::string& brand) : brand_(brand) {std::cout << "Vehicle ctor called.\n";}virtual ~Vehicle(){std::cout << "Vehicle dtor called.\n";}Vehicle(const Vehicle& rhs) : brand_(rhs.brand_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Vehicle& operator=(const Vehicle& rhs) &{Vehicle(rhs).swap(*this);std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}void swap(Vehicle& rhs) noexcept {brand_.swap(rhs.brand_);}Vehicle(Vehicle&& rhs) noexcept: brand_(rhs.brand_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Vehicle& operator=(Vehicle&& rhs) & noexcept {brand_ = rhs.brand_;std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}private:std::string brand_;
};Vehicle getVehicle(){return Vehicle("Tesla");
}int main() {// 调用getVehicle()时仅会调用一次构造函数,并没有调用移动赋值运算符,这是因为存在返回值优化// 所以函数可以直接返回对象,不需要通过出参的方式Vehicle vec1 = getVehicle(); // Vehicle ctor called.Vehicle vec2("BYD"); // Vehicle ctor called.std::cout << std::string(40, '-') << std::endl;vec2 = getVehicle(); // Vehicle ctor called.// Vehicle& Vehicle::operator=(Vehicle&&) &// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;Vehicle vec3(std::move(vec1)); // Vehicle::Vehicle(Vehicle&&)std::cout << std::string(40, '-') << std::endl;std::vector<Vehicle> vecs1(4, Vehicle("LINKO")); // Vehicle ctor called.// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;std::vector<Vehicle> vecs2(4); // Vehicle default-ctor called.// Vehicle default-ctor called.// Vehicle default-ctor called.// Vehicle default-ctor called.std::cout << std::string(40, '-') << std::endl;vecs2.emplace_back(); // Vehicle default-ctor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;vecs2.emplace_back(); // Vehicle default-ctor called.std::cout << std::string(40, '-') << std::endl;vecs2.push_back(Vehicle()); // Vehicle default-ctor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;
}
输出:
Vehicle ctor called.
Vehicle ctor called.
----------------------------------------
Vehicle ctor called.
Vehicle& Vehicle::operator=(Vehicle&&) &
Vehicle dtor called.
----------------------------------------
Vehicle::Vehicle(Vehicle&&)
----------------------------------------
Vehicle ctor called.
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle dtor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle default-ctor called.
Vehicle default-ctor called.
Vehicle default-ctor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
----------------------------------------
Vehicle default-ctor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
----------------------------------------
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
2. 当移动构造未标记noexcept
时该调用移动构造的时候可能调用的是拷贝构造
#include <iostream>
#include <string>
#include <vector>class Vehicle{
public:Vehicle(){std::cout << "Vehicle default-ctor called.\n";}Vehicle(const std::string& brand) : brand_(brand) {std::cout << "Vehicle ctor called.\n";}virtual ~Vehicle(){std::cout << "Vehicle dtor called.\n";}Vehicle(const Vehicle& rhs) : brand_(rhs.brand_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Vehicle& operator=(const Vehicle& rhs) &{Vehicle(rhs).swap(*this);std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}void swap(Vehicle& rhs) noexcept {brand_.swap(rhs.brand_);}Vehicle(Vehicle&& rhs) /*noexcept*/: brand_(rhs.brand_) {std::cout << __PRETTY_FUNCTION__ << std::endl;}Vehicle& operator=(Vehicle&& rhs) & noexcept {brand_ = rhs.brand_;std::cout << __PRETTY_FUNCTION__ << std::endl;return *this;}private:std::string brand_;
};Vehicle getVehicle(){return Vehicle("Tesla");
}int main() {// 调用getVehicle()时仅会调用一次构造函数,并没有调用移动赋值运算符,这是因为存在返回值优化// 所以函数可以直接返回对象,不需要通过出参的方式Vehicle vec1 = getVehicle(); // Vehicle ctor called.Vehicle vec2("BYD"); // Vehicle ctor called.std::cout << std::string(40, '-') << std::endl;vec2 = getVehicle(); // Vehicle ctor called.// Vehicle& Vehicle::operator=(Vehicle&&) &// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;Vehicle vec3(std::move(vec1)); // Vehicle::Vehicle(Vehicle&&)std::cout << std::string(40, '-') << std::endl;std::vector<Vehicle> vecs1(4, Vehicle("LINKO")); // Vehicle ctor called.// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;std::vector<Vehicle> vecs2(4); // Vehicle default-ctor called.// Vehicle default-ctor called.// Vehicle default-ctor called.// Vehicle default-ctor called.std::cout << std::string(40, '-') << std::endl;vecs2.emplace_back(); // Vehicle default-ctor called.// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle::Vehicle(const Vehicle&)// Vehicle dtor called.// Vehicle dtor called.// Vehicle dtor called.// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;vecs2.emplace_back(); // Vehicle default-ctor called.std::cout << std::string(40, '-') << std::endl;vecs2.push_back(Vehicle()); // Vehicle default-ctor called.// Vehicle::Vehicle(Vehicle&&)// Vehicle dtor called.std::cout << std::string(40, '-') << std::endl;
}
输出结果:
Vehicle ctor called.
Vehicle ctor called.
----------------------------------------
Vehicle ctor called.
Vehicle& Vehicle::operator=(Vehicle&&) &
Vehicle dtor called.
----------------------------------------
Vehicle::Vehicle(Vehicle&&)
----------------------------------------
Vehicle ctor called.
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle dtor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle default-ctor called.
Vehicle default-ctor called.
Vehicle default-ctor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle::Vehicle(const Vehicle&)
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
----------------------------------------
Vehicle default-ctor called.
----------------------------------------
Vehicle default-ctor called.
Vehicle::Vehicle(Vehicle&&)
Vehicle dtor called.
----------------------------------------
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.
Vehicle dtor called.