不能使函数接受右值和左值引用
Can't make a function accept both rvalue and lvalue references
class Vec3{
private:
float x, y, z;
public:
Vec3() = default;
Vec3(const float c) {x = c; y = c; z = c;}
static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
};
Vec3 aaa = Vec3( 1.0f);
Vec3 bbb = Vec3::normalize( Vec3( 1.0f));
Vec3 ccc = Vec3::normalize( aaa);
我想编写以向量为参数的函数,对它们进行一些处理并return它们作为参考。
在上面的代码中,bbb
将无法编译,因为它是对右值的非常量引用。我无法将其设为 const,因为 normalize
需要修改对象。如果我让函数接受右值引用 (Vec3&& v
),那么 ccc
将无法编译,因为 aaa
是一个左值。我可以不用编写两个版本的 normalize
来完成这项工作吗?
(我对右值和左值引用感到困惑,例如我不明白为什么 someFunc(const Vec3& v)
会同时接受右值和左值,而非常量版本不会。)
不,你不能。你必须使用两个版本。您可以按照@NathanOliver 的建议将它们组合起来,但您仍然需要两个版本。
I don't understand for example why a someFunc(const Vec3& v) will accept both rvalues and lvalues while the non-const version won't.
因为标准禁止将右值绑定到非常量左值引用。这与
中的问题相同
const int& x = 1; // OK
int& y = 2; // error
似乎该标准试图保护您免受临时文件的意外修改。不幸的是,我真的不能给你更深入的解释。但是你可以阅读这个:
Why not non-const reference to temporary objects?
How come a non-const reference cannot bind to a temporary object?
当然,最后 &&
的发明正是为了实现这一点。所以我猜这更像是历史原因?
您只需花费一点开销即可完成此操作。您不必编写规范化代码两次,但您需要以不同方式处理 returning,因为您不想 return 对右值的引用。
如果你有类似的东西
static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
static Vec3 normalize(Vec3&& v) { return normalize(v);}
^ v is a lvalue here
现在您可以将临时文件转发到左值引用版本,然后 return 按值转发,这样您就不会尝试引用可能不再存在的对象。
class Vec3{
private:
float x, y, z;
public:
Vec3() = default;
Vec3(const float c) {x = c; y = c; z = c;}
static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
};
Vec3 aaa = Vec3( 1.0f);
Vec3 bbb = Vec3::normalize( Vec3( 1.0f));
Vec3 ccc = Vec3::normalize( aaa);
我想编写以向量为参数的函数,对它们进行一些处理并return它们作为参考。
在上面的代码中,bbb
将无法编译,因为它是对右值的非常量引用。我无法将其设为 const,因为 normalize
需要修改对象。如果我让函数接受右值引用 (Vec3&& v
),那么 ccc
将无法编译,因为 aaa
是一个左值。我可以不用编写两个版本的 normalize
来完成这项工作吗?
(我对右值和左值引用感到困惑,例如我不明白为什么 someFunc(const Vec3& v)
会同时接受右值和左值,而非常量版本不会。)
不,你不能。你必须使用两个版本。您可以按照@NathanOliver 的建议将它们组合起来,但您仍然需要两个版本。
I don't understand for example why a someFunc(const Vec3& v) will accept both rvalues and lvalues while the non-const version won't.
因为标准禁止将右值绑定到非常量左值引用。这与
中的问题相同const int& x = 1; // OK
int& y = 2; // error
似乎该标准试图保护您免受临时文件的意外修改。不幸的是,我真的不能给你更深入的解释。但是你可以阅读这个:
Why not non-const reference to temporary objects?
How come a non-const reference cannot bind to a temporary object?
当然,最后 &&
的发明正是为了实现这一点。所以我猜这更像是历史原因?
您只需花费一点开销即可完成此操作。您不必编写规范化代码两次,但您需要以不同方式处理 returning,因为您不想 return 对右值的引用。
如果你有类似的东西
static Vec3& normalize(Vec3& v) {/* normalize */ return v;}
static Vec3 normalize(Vec3&& v) { return normalize(v);}
^ v is a lvalue here
现在您可以将临时文件转发到左值引用版本,然后 return 按值转发,这样您就不会尝试引用可能不再存在的对象。