Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用移动语义重载一元算术_C++_Operator Overloading - Fatal编程技术网

C++ 如何使用移动语义重载一元算术

C++ 如何使用移动语义重载一元算术,c++,operator-overloading,C++,Operator Overloading,我想为std::vector实现一元算术运算符和移动语义。这样做的目的是避免在运算符内部进行内部分配(如果它应用于右值) 问题:以下操作未编译:c=-(a+b) 这不会编译的原因是,为std::vector实现的二进制算术运算符+I返回一个常量左值(因此编译器会抱怨(a+b)=c,这没有意义) 二进制+运算符 template<class T, class AllocVect1, class AllocVect2> inline const std::vector<T>

我想为std::vector实现一元算术运算符和移动语义。这样做的目的是避免在运算符内部进行内部分配(如果它应用于右值)

问题:以下操作未编译:c=-(a+b)

这不会编译的原因是,为std::vector实现的二进制算术运算符+I返回一个常量左值(因此编译器会抱怨(a+b)=c,这没有意义)

二进制+运算符

template<class T, class AllocVect1, class AllocVect2>
inline const std::vector<T> operator+ (
    const std::vector<T, AllocVect1> &v1,
    const std::vector<T, AllocVect2> &v2) {
    std::vector<T> vout;

    *Compute vout = v1 + v2*

    return vout;
}
template<class T, class Alloc>
inline const std::vector<T>& operator- (std::vector<T, Alloc> &&v) {
    std::transform (
        v.begin (), 
        v.end (), 
        v.begin (), 
        [](const auto &val){return -val;});
    return v;
}
模板
内联常量std::向量运算符+(
常数标准::向量和v1,
const std::vector和v2){
std::向量vout;
*计算vout=v1+v2*
退票;
}
一元运算符

template<class T, class AllocVect1, class AllocVect2>
inline const std::vector<T> operator+ (
    const std::vector<T, AllocVect1> &v1,
    const std::vector<T, AllocVect2> &v2) {
    std::vector<T> vout;

    *Compute vout = v1 + v2*

    return vout;
}
template<class T, class Alloc>
inline const std::vector<T>& operator- (std::vector<T, Alloc> &&v) {
    std::transform (
        v.begin (), 
        v.end (), 
        v.begin (), 
        [](const auto &val){return -val;});
    return v;
}
模板
内联常量std::vector和运算符-(std::vector和&v){
std::transform(
v、 begin(),
v、 结束(),
v、 begin(),
[](const auto&val){return-val;});
返回v;
}

通过值传递并返回向量。

当你考虑这些事情时,听起来有点不合常理:

  • 临时对象可以隐式移动到值参数中——不会发生复制。这就好像要对局部变量调用
    std::move

  • 此对象(参数)可以就地修改,因为它没有
    const
    限定符

  • 可以返回修改后的对象,并再次隐式应用移动语义。您永远不应该返回对局部变量的引用——无论是左值引用还是右值引用

  • 模板
    std::vector操作符-(std::vector v){//1。
    std::for_each(//2。
    v、 begin(),
    v、 end(),
    [](T&val){val=-val;});
    返回v;//3。
    }
    
    可以使用右值(移动+修改+移动)和左值(复制+修改+移动)调用此运算符

    也就是说,
    const-Param&
    Param&&
    单独重载有其优点,其细节已在单独的答案中解释:


    通过值传递并返回向量。

    当你考虑这些事情时,听起来有点不合常理:

  • 临时对象可以隐式移动到值参数中——不会发生复制。这就好像要对局部变量调用
    std::move

  • 此对象(参数)可以就地修改,因为它没有
    const
    限定符

  • 可以返回修改后的对象,并再次隐式应用移动语义。您永远不应该返回对局部变量的引用——无论是左值引用还是右值引用

  • 模板
    std::vector操作符-(std::vector v){//1。
    std::for_each(//2。
    v、 begin(),
    v、 end(),
    [](T&val){val=-val;});
    返回v;//3。
    }
    
    可以使用右值(移动+修改+移动)和左值(复制+修改+移动)调用此运算符

    也就是说,
    const-Param&
    Param&&
    单独重载有其优点,其细节已在单独的答案中解释:


    请提供一个正确的答案。您建议的运算符具有令人困惑/惊讶的语义。为什么它返回一个
    const
    引用?请提供一个适当的。您建议的运算符具有令人困惑/惊讶的语义。为什么它返回一个
    const
    引用?感谢您的详细解释!然而,我想知道在下面的作业中会发生什么:autoc=-(a+b);?运算符+返回一个常量左值,这样程序员就不会被引诱去编写类似于:(a+b)=‘其他向量’的东西。但是,由于这个操作符+返回一个常量左值,它会在调用操作符时复制或移动吗?你在回答中写道:
    (a+b)=‘其他向量’
    ——这真的是一个值得保护的用例吗?您多长时间见过这样的代码?如果您还将
    运算符+
    修改为按值返回而不是常量左值,那么一切都将正常工作--您不能分配给未命名的临时值(因此
    (a+b)=
    。是不允许的),并且
    -(a+b)
    将“正常工作”,而无需额外的副本。对于基本类型(a+b)='something'发出编译器错误:赋值的左操作数需要左值。如果有类似的通用类定义了操作符的重载,那该多好啊!谢谢您的详细解释!然而,我想知道在下面的作业中会发生什么:autoc=-(a+b);?运算符+返回一个常量左值,这样程序员就不会被引诱去编写类似于:(a+b)=‘其他向量’的东西。但是,由于这个操作符+返回一个常量左值,它会在调用操作符时复制或移动吗?你在回答中写道:
    (a+b)=‘其他向量’
    ——这真的是一个值得保护的用例吗?您多长时间见过这样的代码?如果您还将
    运算符+
    修改为按值返回而不是常量左值,那么一切都将正常工作--您不能分配给未命名的临时值(因此
    (a+b)=
    。是不允许的),并且
    -(a+b)
    将“正常工作”,而无需额外的副本。对于基本类型(a+b)='something'发出编译器错误:赋值的左操作数需要左值。如果对具有定义的运算符重载的一般类也有类似的情况就好了+