C++-a.empty() ? a : (b.empty() ? b : c) = “asdffdsa”

C++-a.empty() ? a : (b.empty() ? b : c) = “asdffdsa”

想挽留 发布于 2017-09-06 字数 365 浏览 1126 回复 3

代码 1:
C/C++ code

#include <iostream>
#include <string>
using namespace std;

int main()
{
string a, b, c;
a.empty() ? a : (b.empty() ? b : c) = "fkdlsajfa"; // a, b, c 都没有被赋值. 何解?
cout <<a <<endl <<b <<endl <<c <<endl;
return 0;
}

如果你对这篇文章有疑问,欢迎到本站 社区 发帖提问或使用手Q扫描下方二维码加群参与讨论,获取更多帮助。

扫码加入群聊

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

灵芸 2017-10-14 3 楼

 VS2010反汇编结果:

代码1:
a.empty() ? a : (b.empty() ? b : c) = "fkdlsajfa"; // a, b, c 都没有被赋值. 何解?
011A39FA lea ecx,[ebp-34h]
011A39FD call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::empty (11A1064h)
011A3A02 movzx eax,al
011A3A05 test eax,eax
011A3A07 je main+84h (11A3A14h) ;a.empty()成立,不跳转继续执行
011A3A09 lea ecx,[ebp-34h] ;a
011A3A0C mov dword ptr [ebp-164h],ecx
011A3A12 jmp main+0CCh (11A3A5Ch) ;直接跳转到下面的cout行了,完全不涉及到后面的赋值
011A3A14 lea ecx,[ebp-5Ch]
011A3A17 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::empty (11A1064h)
011A3A1C movzx edx,al
011A3A1F test edx,edx
011A3A21 je main+9Eh (11A3A2Eh)
011A3A23 lea eax,[ebp-5Ch]
011A3A26 mov dword ptr [ebp-168h],eax
011A3A2C jmp main+0AAh (11A3A3Ah)
011A3A2E lea ecx,[ebp-84h]
011A3A34 mov dword ptr [ebp-168h],ecx
011A3A3A mov edx,dword ptr [ebp-168h]
011A3A40 mov dword ptr [ebp-15Ch],edx
011A3A46 push offset string "fkdlsajfa" (11A9830h)
011A3A4B mov ecx,dword ptr [ebp-15Ch]
011A3A51 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator= (11A1122h)
011A3A56 mov dword ptr [ebp-164h],eax
cout <<a <<endl <<b <<endl <<c <<endl;
011A3A5C mov esi,esp

代码2:
a.empty() ? a : (b.empty() ? b : c) = "fkdlsajfa"; // c 被赋值.
00B83A09 lea ecx,[ebp-34h]
00B83A0C call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::empty (0B81064h)
00B83A11 movzx eax,al
00B83A14 test eax,eax
00B83A16 je main+93h (0B83A23h) ;a.empty()不成立,跳转到下面注释
00B83A18 lea ecx,[ebp-34h]
00B83A1B mov dword ptr [ebp-164h],ecx
00B83A21 jmp main+0DBh (0B83A6Bh)
00B83A23 lea ecx,[ebp-5Ch] ;a的已经跳过
00B83A26 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::empty (0B81064h)
00B83A2B movzx edx,al
00B83A2E test edx,edx
00B83A30 je main+0ADh (0B83A3Dh) ;b.empty()也不成立,跳转
00B83A32 lea eax,[ebp-5Ch]
00B83A35 mov dword ptr [ebp-168h],eax
00B83A3B jmp main+0B9h (0B83A49h)
00B83A3D lea ecx,[ebp-84h] ;b已经跳过
00B83A43 mov dword ptr [ebp-168h],ecx
00B83A49 mov edx,dword ptr [ebp-168h]
00B83A4F mov dword ptr [ebp-15Ch],edx
00B83A55 push offset string "fkdlsajfa" (0B89830h) ;这里将字符串赋值给了c
00B83A5A mov ecx,dword ptr [ebp-15Ch]
00B83A60 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::operator= (0B81122h)
00B83A65 mov dword ptr [ebp-164h],eax

直接根据汇编结果,代码1根本就不执行后面的赋值操作(1L对的),优先级的确是"?:"比"="高,但是若要给三元运算符赋值是要在外面加个括号的,

 (a.empty() ? a : (b.empty() ? b : c)) = "fkdlsajfa";

C++中类似情况都会出现一些未知结果,就像上面一个赋值成立,一个赋值不成立的情况。
汇编的结果也是一样,加了括号后可跳转到赋值部分。
~~

清晨说ぺ晚安 2017-10-14 2 楼

这个是优先级问题, 你本意是想写成赋值语句, 但是其实不是, 除非你加括号
第一个:
a.empty()为true, 直接返回a,后面的(b.empty() ? b : c) = "fkdlsajfa"没执行
计算过程大概如下:

true ? a:(b.empty() ? b : c) = "fkdlsajfa" ---------> a

第二段:
a.empty()为false, 开始计算(b.empty() ? b : c) = "fkdlsajfa" , 而b.empty()为false, 返回c, c被"fkdlsajfa"赋值
就算过程大概如下:

false ? a : (b.empty() ? b : c) = "fkdlsajfa" => (b.empty() ? b : c) = "fkdlsajfa" --------->
(b.empty() ? b : c) = "fkdlsajfa" => (false ? b:c)= "fkdlsajfa" --------->
c = "fkdlsajfa" ---------> c

甜柠檬 2017-10-13 1 楼

我来补充likebeta的答案吧,a.empty() ? a : (b.empty() ? b : c) = "fkdlsajfa";是拆分成a.empty() ?v1:v2,其中v1=a,v2=(b.empty() ? b : c) = "fkdlsajfa",你可以自己再试下a.empty() ? (cout<<"an",a) : (b.empty() ? (cout<<"bn",b) :(cout<<"cn",c)) = (cout<<"testn","fkdlsajfa"); 输出的结果是a,不会执行到test那里