转移运算符:<<
>>
逐位运算符:~
,&
,^
,|
sizeof运算符:sizeof()
根据C ++标准(n3797),我只能确认~
产生prvalue(5.3.1 / 2),而不是上面的其他产品。
答案 0 :(得分:1)
据我所知,结果是 prvalues ,但这只是一种推测。这似乎与What is the value category of the operands of C++ operators when unspecified?和Does the standard mandate an lvalue-to-rvalue conversion of the pointer variable when applying indirection?中涵盖的操作数值类别的方式类似。
我们可以从3.10
部分看到Lvalues和rvalues 有以下注释:
第5章中对每个内置运算符的讨论表明了 它产生的价值的类别和价值的类别 它期望的操作数。
但正如我们所看到的,5
部分仅在少数情况下明确说明了值类别。对于此特定问题,仅明确说明&
和~
的结果的值类别。
即使它没有明确规定,我们也能找到指向一致方向的线索。我们可以提出一个论点,即>>
,<<
,^
和|
的操作数转换为 prvalues 。这并没有规定结果的值类别,但它确实将结果排除在 xvalue 之后,根据{em> 7 段,其中包含以下注释:
表达式是xvalue,如果它是:
- 调用的结果 函数,无论是隐式还是显式,其返回类型是 rvalue对象类型的引用,
- 对rvalue引用的强制转换 对象类型,
- 指定a的类成员访问表达式 非对象类型的非静态数据成员 表达式是xvalue,或
- a。*指向成员的指针表达式 其中第一个操作数是xvalue,第二个操作数是a 指向数据成员的指针。
一般来说,这条规则的效果就是这样 命名的右值引用被视为左值和未命名的右值 对象的引用被视为xvalues;右值引用 无论是否命名,函数都被视为左值。
我没有看到任何合理的论据,结果可能是左值,因此基本上没有 prvalue 。
所以细节如下:
部分5
一元运算符段 2 涵盖~
和&
,其中包含:
以下每个一元运算符的结果都是prvalue。
班次运营商需要整合的促销活动,其中包含5.3.1
Shift运算符段 1 部分,其中包含:
操作数应为整数或无范围的枚举类型,并执行整体促销。
我们可以看到整体促销活动需要<{1}} 整体促销中的 prvalues ,其中每个段落都以:
开头[...]
的prvalue
5.8
和4.5
都需要通常的算术转换并且都说:
运算符仅适用于整数或无范围枚举操作数
因此通常的算术转换的最后一个子句适用于:
否则,应对两个操作数执行整数提升(4.5)。 59
经验方法
Luc Danton在他对Empirically determine value category of C++11 expression?的回答中有一种确定表达式价值范畴的经验方法。该方法使用以下代码:
^
并且答案概述了如下逻辑:
左值表达式产生左值引用类型,x值为 一个右值引用类型,以及一个只有该类型的prvalue。
以下示例均产生 prvalue ( see it live ):
|
答案 1 :(得分:0)
sizeof():size_t根据标准5.3.3 pt6 - 标准5.19 / 3表示&#34;整数常量表达式是整数或未整数枚举类型的表达式,隐式转换为prvalue,其中转换后的表达式是一个核心常数表达式。&#34;从5.3.3 / 6和18.2 / 6可以推断出它是一个prvalue。
E1&lt;&lt; E2和E1>&gt; E2:标准5.8.1&#34;操作数应为整数或无范围的枚举类型,并执行整体促销。结果的类型是提升的左操作数的类型。&#34;。根据标准4.5和特定的第7页,积分促销意味着prvalue。
&安培; |和^:标准指定&#34;执行通常的算术转换; (...)运算符仅适用于整数或无范围的枚举操作数&#34;。
答案 2 :(得分:-2)
cppreference说明以下功能:
prvaule (&#34; pure&#34; rvalue)是一个标识临时对象(或其子对象)的表达式,或者是与任何对象无关的值。
以下表达式是prvalues:
这适用于功能,我不确定有关内置运营商的规则究竟是什么。
答案 3 :(得分:-3)
有一些小东西: http://rextester.com/DUEJY28518:
std::cout << typeid(decltype(sizeof(char))).name() << std::endl;
std::cout << typeid(decltype(1 << 1)).name() << std::endl;
std::cout << typeid(decltype(1 >> 1)).name() << std::endl;
std::cout << typeid(decltype(~1)).name() << std::endl;
std::cout << typeid(decltype(1 & 1)).name() << std::endl;
std::cout << typeid(decltype(1 | 1)).name() << std::endl;
std::cout << typeid(decltype(1 ^ 1)).name() << std::endl;
std::cout << "-------------" << std::endl;
std::cout << typeid(decltype(1U << 1)).name() << std::endl;
std::cout << typeid(decltype(1U >> 1)).name() << std::endl;
std::cout << typeid(decltype(~1U)).name() << std::endl;
std::cout << typeid(decltype(1U & 1)).name() << std::endl;
std::cout << typeid(decltype(1U | 1)).name() << std::endl;
std::cout << typeid(decltype(1U ^ 1)).name() << std::endl;
std::cout << "-------------" << std::endl;
std::cout << typeid(decltype(1L << 1)).name() << std::endl;
std::cout << typeid(decltype(1L >> 1)).name() << std::endl;
std::cout << typeid(decltype(~1L)).name() << std::endl;
std::cout << typeid(decltype(1L & 1)).name() << std::endl;
std::cout << typeid(decltype(1L | 1)).name() << std::endl;
std::cout << typeid(decltype(1L ^ 1)).name() << std::endl;
结果是(MSVC):
unsigned int
int
int
int
int
int
int
-------------
unsigned int
unsigned int
unsigned int
unsigned int
unsigned int
unsigned int
-------------
long
long
long
long
long
long