C++ 无法使函数同时接受右值和左值引用

C++ 无法使函数同时接受右值和左值引用,c++,code-duplication,rvalue,lvalue,C++,Code Duplication,Rvalue,Lvalue,我想写一些函数,将向量作为参数,对它们做一些处理,并将它们作为引用返回 在上面的代码中,bbb不会编译,因为它是对右值的非常量引用。我无法将其设置为常量,因为normalize需要修改对象。如果我让函数接受右值引用Vec3&&v,那么ccc不会编译,因为aaa是左值。我可以在不必编写两个版本的normalize的情况下完成这项工作吗 我对右值和左值引用感到困惑,例如,我不明白为什么someFuncconst Vec3&v会同时接受右值和左值,而非常量版本则不会。不,你不能。您必须使用两个版本。您

我想写一些函数,将向量作为参数,对它们做一些处理,并将它们作为引用返回

在上面的代码中,bbb不会编译,因为它是对右值的非常量引用。我无法将其设置为常量,因为normalize需要修改对象。如果我让函数接受右值引用Vec3&&v,那么ccc不会编译,因为aaa是左值。我可以在不必编写两个版本的normalize的情况下完成这项工作吗


我对右值和左值引用感到困惑,例如,我不明白为什么someFuncconst Vec3&v会同时接受右值和左值,而非常量版本则不会。不,你不能。您必须使用两个版本。您可以按照@NathanOliver的建议将它们组合起来,但仍然需要两个版本

例如,我不理解为什么someFuncconst Vec3&v会同时接受右值和左值,而非常量版本不会

因为标准禁止将右值绑定到非常量左值ref。这与中的问题相同

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);
似乎该标准正试图保护您免受临时文件的意外修改。不幸的是,我不能给你更深刻的解释。但你可以读到:


当然,到了最后,&&的发明正是为了实现这一点。所以我想这更像是一个历史原因?

不,你不能。您必须使用两个版本。您可以按照@NathanOliver的建议将它们组合起来,但仍然需要两个版本

例如,我不理解为什么someFuncconst Vec3&v会同时接受右值和左值,而非常量版本不会

因为标准禁止将右值绑定到非常量左值ref。这与中的问题相同

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);
似乎该标准正试图保护您免受临时文件的意外修改。不幸的是,我不能给你更深刻的解释。但你可以读到:


当然,到了最后,&&的发明正是为了实现这一点。所以我想这更像是一个历史原因?

您可以用一点开销来完成这项工作。您不必编写两次规范化代码,但需要以不同的方式处理返回,因为您不希望返回对右值的引用

如果你有

const int& x = 1;  // OK
int& y = 2;  // error

现在,您可以将tempoary转发到左值引用版本,然后按值返回,这样您就不会试图引用一个可能不再存在的对象。

您可以用一点开销来完成此操作。您不必编写两次规范化代码,但需要以不同的方式处理返回,因为您不希望返回对右值的引用

如果你有

const int& x = 1;  // OK
int& y = 2;  // error

现在,您可以将tempoary转发到左值引用版本,然后按值返回,这样您就不会试图引用一个可能不再存在的对象。

这可能会回答您关于为什么临时可以绑定到常量引用的一些困惑:这可能会回答您关于为什么临时可以绑定到常量引用的一些困惑: