Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.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_Initializer List - Fatal编程技术网

C++ 为什么我可以使用运算符+;=但不是运算符+;?

C++ 为什么我可以使用运算符+;=但不是运算符+;?,c++,operator-overloading,initializer-list,C++,Operator Overloading,Initializer List,这是对的后续行动,通过查看解决了此问题 考虑下面的C++代码,你可以: #包括 #包括 使用名称空间std; 结构AddInitializerList{ void运算符+=(初始值设定项\u列表值){ //无所事事 } void运算符+(初始值设定项\u列表值){ //无所事事 } }; int main(){ 加法器; 加法器+={1,2,3};//完全合法 加法器+{1,2,3};//不好! 返回0; } main中使用operator+和大括号内的初始值设定项列表的行没有编译(在问了前面

这是对的后续行动,通过查看解决了此问题

考虑下面的C++代码,你可以:

#包括
#包括
使用名称空间std;
结构AddInitializerList{
void运算符+=(初始值设定项\u列表值){
//无所事事
}
void运算符+(初始值设定项\u列表值){
//无所事事
}
};
int main(){
加法器;
加法器+={1,2,3};//完全合法
加法器+{1,2,3};//不好!
返回0;
}
main
中使用
operator+
和大括号内的初始值设定项列表的行没有编译(在问了前面的问题后,我现在知道为什么会这样)。但是,我不明白为什么在
main
中使用
opeartor+=
的代码确实可以很好地编译


我不明白为什么我可以重载
+=
并让它正常工作,而重载
+
在这里似乎不起作用。本标准中是否有特殊规定,允许在
+=
运算符的上下文中使用括号括起的初始值设定项,但不允许在
+
运算符的上下文中使用括号括起的初始值设定项?或者这只是一个奇怪的编译器怪癖?

+=
运算符是一个复合赋值。该标准明确允许在赋值的右侧列出初始值设定项:

§8.5.4/1[…]注:可使用列表初始化

-在作业的右侧(5.17)

§5.17讨论所有任务,包括复合任务:

赋值表达式:
-条件表达式
-逻辑或表达式赋值运算符初始值设定项子句
-抛出表情

赋值运算符:其中一个

=
*=
/=
%=
+=
-=
的答案中对此进行了解释(链接自您链接的问题)

语言语法只允许在某些语法上下文中使用大括号列表,而不能代替任意表达式。该列表包括赋值运算符的右侧,但通常不包括运算符的右侧

+=
是赋值运算符,
+
不是

赋值表达式的语法为:

赋值表达式: 条件表达式 逻辑或表达式赋值运算符初始值设定项子句 抛出表情 赋值运算符:其中一个
=*=*=/=%=+=-=>=C++14第5.17/9节:

括号内的初始列表可能会出现在

  • 标量赋值,在这种情况下,初始值设定项列表最多只能有一个元素。
    x={v}
    的含义,其中
    T
    是表达式
    x
    的标量类型,是
    x=T{v}
    的含义。
    x={}
    的意思是
    x=T{}
  • 对类类型对象的赋值,在这种情况下,初始值设定项列表作为参数传递给重载解析(13.5.3,13.3)选择的赋值运算符函数
这适用于a
+=
b,其$5.7/7等价于a
=
a
+
b(除了a仅为
+=
计算一次)。换句话说,由于M.M.的评论,由于内置运算符的等价性,
+=
被视为赋值运算符,而不是特殊的更新运算符。
因此,上面引用的关于“赋值”的文本适用于
+=

您没有指定编译器,但我用gcc 6.3.1重现了这个失败,它用“error:expected primary expression before'{'token.”向我咆哮。我猜所有赋值运算符都支持大括号。和
adder+initializer\u list{1,2,3};
工作得很好。是的,
加法器。运算符+({1,2,3});
也工作得很好。这很有趣。我似乎找不到任何关于
加法器+{1,2,3}的歧义
。想知道为什么会做出这样的决定。是的,这个猜测是正确的。C++14§5.17/9。这是因为
a+=b
匹配赋值表达式的语法,而不是因为与
a=a+b
等价(在重载运算符的情况下甚至不是这样).5.17/7仅指非过载情况;见第条开头的第3点5@M.M.你是对的,这是一个微不足道的观察结果。你可以通过声称该标准在$5部分中存在缺陷来让它变得更有趣,因为它没有涵盖Q/a I链接中所涵盖的用户定义的
+=
@NeilButterworthLH,这肯定能解释问题。谢谢!我不认为这是一个答案。问题是为什么语法允许
+=
使用大括号init list,而不允许
+
使用大括号init list。列出特定的语法规则只是说明OP在语法允许的方面没有错。@cheers和hth.-Alf The OP,verbatim,“标准中是否有特殊规定允许在+=运算符而不是+运算符的上下文中使用括号括起的初始值设定项?“@cheers-sandhth.-Alf你问的问题非常非常好。我读过一些其他答案,其中引用了一些人的话,他们说这个决定主要是基于使解析器更容易实现,所以我怀疑这就是这里发生的事情(为什么我没有特别问这个问题)。
#include <iostream>
#include <initializer_list>
using namespace std;

struct AddInitializerList {
    void operator+= (initializer_list<int> values) {
        // Do nothing   
    }

    void operator+ (initializer_list<int> values) {
        // Do nothing
    }
};

int main() {
    AddInitializerList adder;
    adder += {1, 2, 3};  // Totally legit
    adder +  {1, 2, 3};  // Not okay!

    return 0;
}
assignment-expression: conditional-expression logical-or-expression assignment-operator initializer-clause throw-expression assignment-operator: one of
= *= *= /= %= += -= >>= <<= &= ^= |=