- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
下面的代码片段编译
#include <iostream>
int& f() { static int i = 100; std::cout << i << '\n'; return i; }
int main()
{
int& r = f();
r = 101;
f();
}
并打印值(live example)
100
101
现在,阅读 N4140 中的 §8.5.3/5,我可以看到它编译是因为要点 (5.1.1),即引用是左值引用,初始化表达式是左值和 int
与 int
(或 int&
- 我不确定我应该在这里使用哪个)引用兼容。
要点 (5.1) 和 (5.1.1):
— If the reference is an lvalue reference and the initializer expression
— is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with
“cv2 T2,” or ...
现在假设我将声明 int& r = f();
中的左值引用更改为右值引用,即 int&& r = f();
.我知道代码不会编译,因为右值引用不会绑定(bind)到左值。但我很好奇的是,如何使用标准得出这个结论?
我会解释我的困难是什么:
int&& r = f();
包含在要点 (5.2) 中,因为引用是右值引用。要点 (5.2):
— Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.
int
与 int
(或 int&
).要点 (5.2.1) 和 (5.2.1.1):
— If the initializer expression
— is an xvalue (but not a bit-field), class prvalue, array prvalue or function
lvalue and “cv1 T1” is reference-compatible with “cv2 T2”, or ...
编辑
我逐字包含了 N4140 (C++14) 中的要点,它们等同于 N3337 (C++11) 中的类似要点。
最佳答案
the initializer expression is an lvalue and
int
is reference-compatible withint
(or withint&
- I don't know for sure which one I should use here).
引用兼容性是应用于引用类型的关系,而不是引用类型。例如,[dcl.init.ref]/5 谈到通过类型 cv2 T1
的表达式初始化“对类型 cv1 T2
的引用”,以及后来比较例如“其中 T1
与 T2
不相关”。
表达式的类型 f()
只是int
,尽管 f
的返回类型是int&
.当我们观察它们时,表达式根本没有引用类型(*);引用被剥离并用于确定值类别(见 [expr]/5)。对于 int& f()
, 表达式 f()
是左值;对于 int g()
, 表达式 g()
是右值。
(*)准确地说,表达式 can have reference type in the Standard ,但仅作为“初始”结果类型。该引用“在任何进一步分析之前”被删除,这意味着该引用根本无法通过该类型观察到。
Now suppose I change the left value reference in the declaration
int& r = f();
by a right value reference, i.e.,int&& r = f();
. I know the code won't compile, as an rvalue reference doesn't bind to an lvalue. But what I'm curious is, how to reach this conclusion using the Standard?
从评论中的讨论来看,困惑似乎是 f()
不是函数左值。 “左值”和“右值”等值类别是表达式的属性。因此,术语“函数左值”必须指代一个表达式,即 具有值类别“左值” 的函数类型表达式。
但是表达式 f()
是一个函数调用表达式。从语法上讲,它是一个后缀表达式,后缀是函数参数列表。根据 [expr.call]/10:
A function call is an lvalue if the result type is an lvalue reference type or an rvalue reference to function type, an xvalue if the result type is an rvalue reference to object type, and a prvalue otherwise.
和 [expr.call]/3
If the postfix-expression designates a destructor [...]; otherwise, the type of the function call expression is the return type of the statically chosen function [...]
也就是说,表达式的(观察到的见上文)类型f()
是int
,值类别为“左值”。请注意,(观察到的)类型不是 int&
.
函数左值例如是一个id-expression,如f
,间接函数指针的结果,或产生任何类型的函数引用的表达式:
using ft = void();
void f();
ft& l();
ft&& r();
ft* p();
// function lvalue expressions:
f
l()
r()
*p()
[expr.prim.general]/8 指定那些标识符,如 f
作为id-expressions,左值是:
An identifier is an id-expression provided it has been suitably declared. [...] The type of the expression is the type of the identifier. The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise.
回到例子int&& r = f();
.使用一些 N4296 之后的草稿。
[dcl.init.ref]
5 A reference to type “cv1
T1
” is initialized by an expression of type “cv2T2
” as follows:
- (5.1) If the reference is an lvalue reference and the initializer expression
引用是一个右值引用。 5.1 不适用。
- (5.2) Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be
const
), or the reference shall be an rvalue reference. [example omitted]
这适用,引用是右值引用。
- (5.2.1) If the initializer expression
- (5.2.1.1) is an xvalue (but not a bit-field), class prvalue, array prvalue or function lvalue and [...], or
- (5.2.1.2) has a class type (i.e.,
T2
is a class type) [...]
初始化器是一个 int
类型的左值. 5.2.1 不适用。
- (5.2.2) Otherwise:
- (5.2.2.1) If
T1
orT2
is a class type [...]- (5.2.2.2) Otherwise, a temporary of type “cv1
T1
” is created and copy-initialized (dcl.init) from the initializer expression. The reference is then bound to the temporary.
最后,5.2.2.2 适用。然而:
If
T1
is reference-related toT2
:
- (5.2.2.3) cv1 shall be the same cv-qualification as, or greater cv-qualification than, cv2; and
- (5.2.2.4) if the reference is an rvalue reference, the initializer expression shall not be an lvalue.
T1
和 T2
是int
(f()
的返回类型的引用被删除,仅用于确定值类别),因此它们是引用相关的。 cv1 和 cv2 都是空的。 引用是右值引用,f()
是左值,因此 5.2.2.4 使程序格式错误。
术语“函数左值”出现在 5.2.1.1 中的原因可能与“函数右值”问题有关(例如,参见 N3010 - Rvalue References as "Funny" Lvalues)。 C++03 中没有函数右值,委员会似乎不想在 C++11 中引入它们。没有右值引用,我认为不可能获得函数右值。例如,您不能转换为函数类型,也不能从函数返回函数类型。
可能为了保持一致性,函数左值可以通过强制转换绑定(bind)到函数类型的右值引用:
template<typename T>
void move_and_do(T& t)
{
T&& r = static_cast<T&&>(t); // as if moved
}
int i = 42;
move_and_do(i);
move_and_do(f);
但对于 T
是像 void()
这样的函数类型, static_cast<T&&>(t)
的值类别是左值(没有函数类型的右值)。因此,对函数类型的右值引用可以绑定(bind)到函数左值。
关于c++ - 我在解释 N4140 的§8.5.3/5 段中的要点 (5.2.1.1) 时遇到了一些困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27840925/
tuple :: (Integer a,Fractional b) => (a,b,String) tuple = (18,5.55,"Charana") 所以这是给我的错误 ‘Integer’ is
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 11 年前。 Improve thi
我已经习惯了python和django,但我最近开始学习java。由于工作原因我没有太多时间,所以错过了很多类(class),现在我有点困惑,我必须做作业。 编辑 该程序应该根据每个运动员在自行车和比
这是一个困难的问题,但对专业人士来说很容易。 我在 mysql 中有以下字段:产品名称、mycost、sellprice 和 stock。因为我需要知道每种产品对我的商店的投资有多少,所以我创建了以下
我有 3 个表,其中已包含以下行: TBL_TESTER_LIST id tester_type tester_name 1 LMX LMX-01 2 LMX
我想只使用 GridBagLayout 来布局组件,如图所示。 我已经尝试了几个约束,但它永远不会以预期的结果结束,所以我想知道仅使用 GridBagLayout 是否真的可行。难点在于C1、C2、C
我遇到了以下代码没有结果的问题。但是,如果我取消注释掉指定的行,并注释掉它起作用的 bind_param 行,但这不是破坏了 mysqli 的目的吗?我的 var_dump 给了我的字符串(1)“1”
这个问题在这里已经有了答案: a good python to exe compiler? [closed] (3 个答案) 关闭 9 年前。 有了我之前问题的一些有用答案(见下文),我决定再试一次
我正在使用 Hadoop 分析 GSOD 数据 (ftp://ftp.ncdc.noaa.gov/pub/data/gsod/)。我选择了 5 年来执行我的实验 (2005 - 2009)。我配置了一
我在我的 macOS 应用程序的设置面板中使用 NSGridView。我是这样设置的: class GeneralViewController: RootViewController { pr
我正在尝试使用以下代码在 PHP 中自动安装 WordPress 发行版: $base_dir = '/home/username/wordpress_location'; chdir($base_d
在 Node.js 中将图像转换为 Base64 字符串时,我遇到了一个非常令人困惑的问题 这是我的示例代码: app.get('/image', (req, res) => { ServerAP
我在尝试运行我的应用程序时遇到一些错误,这里是 logcat java.lang.RuntimeException: Unable to instantiate activity Componen
基本上,我正在努力创建一个管理团队和球员的 Java 程序。 根据我的理解,我会有一个团队和一个玩家类。在团队类中会有 get 和 set 方法,以及某种形式的集合来正确存储球员,例如数组列表?然后在
我仍在尝试找出 JavaSwing 中的 BorderLayout,这真的很令人沮丧。 我希望能够将一个 Pane 拆分为 3 个包含的子面板,但我不完全确定如何包含它。 这是我的游戏类,它包含面板
下面的表设计(完整的模式见下文)还有很多需要改进的地方,并且已经造成了许多困难,但是我无法找出如何最好地将它们规范化。这些表格的目的是: ICD9-提供CICD9和CDESC组合的主查找。每个组合在I
这是我的表格: AB元组表 C 表,其中包含 A.id 和 B.id 的条目 D 表,其中包含带有 C.id 的条目和一个 bool 字段“open” 我想计算 D 表中“open”= true 且具
我在 YouTube 上跟踪了一个相当旧的教程,在视频中他以这种方式使用了 mysql_result: return (mysql_result($result,0) == 1) ? true : f
我正在尝试创建一个左侧面板的页面。该面板有一个页眉、一个内容区域和一个页脚。主面板包装器 div 应该是页面高度的 100%。页眉和页脚没有指定的高度,因为我只希望它们足够大以容纳其文本和填充,而我希
我有 TreeView ,我想在其中显示用户通过 file_dialog.getOpenFileNames() 选择的文件; file_dialog 是 QFileDialog。我确实创建了模型类:
我是一名优秀的程序员,十分优秀!