Для контекста фактический класс, с которым я работаю, значительно сложнее и больше, чем я здесь показываю, но я использую это как пример.
struct Vector {
int x, y;
Vector() : Vector(0,0) {}
Vector(int x, int y) : x(x), y(y) {}
};
Я хотел бы добавить перегрузки оператора, чтобы добавить и вычесть Vector
друг друга.
Vector& operator+=(Vector const& v) {
x += v.x;
y += v.y;
return *this;
}
Vector operator+(Vector const& v) const {
return Vector(*this) += v;
}
Vector& operator-=(Vector const& v) {
x -= v.x;
y -= v.y;
return *this;
}
Vector operator-(Vector const& v) const {
return Vector(*this) -= v;
}
Однако этот код может допускать неудачные построения:
int main() {
Vector & a = Vector(1,2) += Vector(5,4);//This compiles and invokes undefined behavior!
std::cout << a.x << ',' << a.y << std::endl;//This isn't safe!
}
Итак, я переписал код, чтобы помнить, является ли объект L-значением или R-значением:
Vector& operator+=(Vector const& v) & {
x += v.x;
y += v.y;
return *this;
}
Vector&& operator+=(Vector const& v) && {
return std::move(*this += v);
}
Vector operator+(Vector const& v) const {
return Vector(*this) += v;
}
Vector& operator-=(Vector const& v) & {
x -= v.x;
y -= v.y;
return *this;
}
Vector&& operator-=(Vector const& v) && {
return std::move(*this -= v);
}
Vector operator-(Vector const& v) const {
return Vector(*this) -= v;
}
Итак, мой оставшийся вопрос заключается в том, что, хотя этот код компилируется и выполняет то, что я ожидаю, этот код безопасен и не содержит неожиданных Undefined Поведение?
int main() {
//No Longer compiles, good.
//Vector & a = Vector(1,2) += Vector(5,4);
//Is this safe?
Vector b = Vector(1,2) += Vector(5,4);
//Other cases where this code could be unsafe?
}