问题标签 [reference-binding]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 从共享指针转换为指向 const 的共享指针
以下代码无法编译:
如何从共享指针转换为指向常量对象的共享指针?static_cast
也失败了。
c++ - const 引用是否绑定到另一个从临时悬空引用投射的引用?
下面是代码片段:
在这个在线编译器中,输出是
所以返回值似乎比cout
操作更早破坏。所以这instance
似乎是一个悬而未决的参考。
如果我们更改const B& instance = (const B&)func();
为 const B& instance =func();
,那么结果是
作为补充,如果我在vs2015中测试代码,那么输出就是最后一个。但是,如果在gcc(4.6 之前)中测试,输出是前者,但在 4.6 之后的版本中是后者。所以我想知道是在线编译器错误还是引用实际上是悬空的。
c++ - 左值和右值作为函数参数
我试图理解 C++ 中的左值和右值。
所以我将它们用作传递给函数的参数。在第一种情况下,我有两个函数,第一个引用了一个 const int,在这种情况下,感谢“const”(参见链接),我可以将 Lvalue 和 Rvalue 都传递给第一个函数,我不会有任何问题. 相反,在第二个函数中,我必须传递一个 Rvlaue,否则我会得到描述的错误。
好的!
为什么如果第二个函数成为函数模板,如下例所示,我也可以传递一个左值。
c++ - 最佳可行转换函数
在下面的程序中,应该选择哪个(如果有)转换函数,为什么?
gcc 和 clang select 都选择转换函数#2。但为什么?
标准说:
(1) 在 [dcl.init.ref] 中指定的条件下,引用可以直接绑定到将转换函数应用于初始化表达式的结果。重载分辨率用于选择要调用的转换函数。假设“reference to cv1 T”是被初始化的引用的类型,“cv S”是初始化表达式的类型,其中S是类类型,候选函数选择如下:
(1.1) - 考虑 S 及其基类的转换函数。那些未隐藏在 S 中并产生类型“对 cv2 T2 的左值引用”(初始化对函数的左值引用或右值引用时)或“cv2 T2”或“对 cv2 T2 的右值引用”(当初始化对函数的右值引用或左值引用),其中“cv1 T”与“cv2 T2”引用兼容,是候选函数。对于直接初始化,那些不隐藏在 S 中并产生类型“对 cv2 T2 的左值引用”(当初始化对函数的左值引用或右值引用时)或“对 cv2 T2 的右值引用”(当初始化一个右值引用或函数的左值引用),
(2) 参数列表有一个参数,即初始化表达式。[ 注意:此参数将与转换函数的隐式对象参数进行比较。——尾注]
这里我们有两个候选函数#1 和#2。两者都是可行的——如果其中一个被删除,程序仍然可以编译。两个转换函数都只采用隐式参数,并且具有相同的 cv- 和 ref-qualification。所以没有一个应该是最好的,程序不应该编译。为什么会编译?
c++ - 为什么 double 可以转换为看似任何原语的 const 引用?
考虑以下代码:
尽管我将 a 传递double
给一个函数,该函数接受对小于 a 的类型的 const 引用double
(在我的系统上,sizeof(double) == 8
, whilesizeof(unsigned int) == 4
和sizeof(char) == 1
根据定义),但它仍会编译并运行。如果引用不是const
,则编译失败(例如, float func(char & val1, unsigned int & val2)
而不是当前定义)并出现错误:
无法将“char&”类型的非常量左值引用绑定到“char”类型的右值
在 Godbolt 上使用 GCC、Clang、ICC 和 MSVC 进行测试时,我得到了完全相同的行为,因此它看起来是标准的。什么是 const-references 导致它被接受,而引用却不是?另外,我使用-Wall -pedantic
了 - 为什么我没有收到有关缩小转换的警告?当函数通过值而不是通过引用传递时,我会这样做......
c++ - C++ - 使用 const 引用来延长一个临时的、好的或 UB 的成员?
考虑这样的事情:
当我用 -O0 编译时,我得到了打印
但是当我用 -O2 编译时,我得到了
我知道我们可以使用 const 引用来延长本地临时,所以像
将是完全合法的。但我正在努力寻找为什么相同的机制/规则不适用于任何临时的原因
编辑以供将来参考:
我正在使用 gcc 版本 6.3.0
c++ - 可以通过 const 引用返回默认参数的值吗?
是否可以通过 const 引用返回默认参数的值,如下例所示:
c++ - 形成对对象的引用是否构成访问?
形成对对象的引用是否构成访问?
这是 GCC 和 Clang 目前所做的:
我的问题是关于声明的
- 根据抽象机,这是否读取 指向的对象的值
ptr
? 如果单独来看,这个语句会是未定义的行为ptr == nullptr
吗?- 是的,空指针的间接寻址是 UB - https://stackoverflow.com/a/59205697/1614051
- 如果
ptr
指向除 之外的其他东西,是否会违反混叠int
?
请注意,我专门询问如何形成参考,而不是使用它来读取值。
编辑 09/12/2019:接受以下答案:
- 是否
int const volatile& ref = *ptr;
读取指向对象的值?- 不。
- 这是未定义的时间
ptr == nullptr
吗?- 是的,
*ptr
在空指针上是未定义的。
- 是的,
ptr
如果指向不同类型的对象, 形成引用是否违反了别名?- 不,只是形成引用并不违反严格的别名。
- 大概
reinterpret_cast
-ing 对正确类型的引用是允许且有效的。
c++ - 在引用初始化中使用已删除的复制构造函数进行复制初始化
考虑以下代码:
如果 T1 或 T2 是类类型,并且 T1 与 T2 没有引用相关,则使用通过用户定义转换([ dcl.init ], [over.match.copy], [over.match.conv]); 如果相应的非参考复制初始化格式错误,则程序格式错误。调用转换函数的结果,如针对非引用复制初始化所描述的,然后用于直接初始化引用。对于这种直接初始化,不考虑用户定义的转换
否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换被枚举,如 [over. match.copy],并通过重载决议([over.match])选择最佳的。如果转换无法完成或不明确,则初始化格式错误。以初始化表达式作为参数调用所选函数;如果函数是构造函数,则调用是目标类型的 cv 非限定版本的纯右值,其结果对象由构造函数初始化。该调用用于根据上述规则直接初始化作为复制初始化目标的对象。
按照标准, 的类型a
是int
,初始化引用的类型是Data
,所以 fromint
到Data
,用户定义的转换被认为是使用通过用户定义转换复制初始化类型为“cv1 T1”的对象的规则. 意思是Data const& d_rf = a;
可以翻译成Data temporary = a; Data const& d_rf = temporary;
。因为Data temporary = a;
,即使存在复制省略,也必须检查复制/移动构造函数是否可用,但复制构造函数已经被删除,class Data
为什么还能编译呢?
以下是 来自 enseignement 的引用的标准
复制初始化的一些引用
从 cppreference 复制引用的初始化
如果引用是左值引用:
如果 object 是左值表达式,并且它的类型是 T 或从 T 派生,并且具有相同或更少的 cv 限定,则引用绑定到由左值标识的对象或其基类子对象。
如果 object 是左值表达式,并且其类型可隐式转换为 T 或派生自 T 的类型,同等或更少 cv 限定,则源类型及其返回左值的基类的非显式转换函数考虑参考,并通过重载决议选择最好的参考。然后将引用绑定到由转换函数返回的左值标识的对象(或其基类子对象)否则,如果引用是对 const 的右值引用或左值引用:
如果 object 是 xvalue、类纯右值、数组纯右值或 T 或从 T 派生的函数左值类型,同样或更少 cv 限定,则引用绑定到初始化表达式的值或其基础子对象。
如果 object 是一个类类型表达式,可以隐式转换为 xvalue、类纯右值或类型为 T 或派生自 T 的函数值,同样或更少 cv 限定,则引用绑定到结果转换或其基础子对象。
否则,将构造一个 T 类型的临时对象并从对象复制初始化。然后引用绑定到这个临时。应用复制初始化规则(不考虑显式构造函数)。
[例子:
常量 std::string& rs = "abc"; // rs 指的是从 char 数组 中初始化的临时复制]
更新:
我们考虑N337下的代码
根据标准,值a
的类型是int
,引用所指的目的类型是Data
,所以编译器需要Data
通过拷贝初始化生成一个临时的类型。这里毫无疑问,所以我们专注于拷贝初始化。源类型是int
目标类型是Data
,这种情况符合:
否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换序列被枚举,如 13.3 中所述。 1.4,最好的一个是通过重载决议(13.3)选择的。如果转换无法完成或不明确,则初始化格式错误。以初始化表达式作为参数调用所选函数;如果函数是构造函数,则调用初始化目标类型的 cv 非限定版本的临时版本。临时是prvalue。然后根据上述规则,调用的结果(对于构造函数的情况是临时的)用于直接初始化作为复制初始化目标的对象。在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除这种直接初始化中固有的复制;
注意粗体部分,并不表示该值int
直接将临时值初始化为Data::Data(int)
。这意味着,int
首先转换为Data
by Data::Data(int)
,然后此结果直接初始化临时对象,即此处复制初始化的目标对象。如果我们用代码来表达粗体部分,就像Data temporary(Data(a))
.
上面的规则在这里:
— 如果初始化是直接初始化,或者如果是复制初始化,其中源类型的 cv 非限定版本与目标类相同或派生类,则考虑构造函数。枚举了适用的构造函数(13.3.1.3),并通过重载决议(13.3)选择最佳构造函数。调用如此选择的构造函数来初始化对象,使用初始化表达式或表达式列表作为其参数。如果没有构造函数适用,或者重载决议不明确,则初始化格式错误。
请重新返回Data temporary(Data(a))
。显然,复制/移动构造函数是参数 Data(a) 的最佳匹配。但是,Data(Data const&) = delete;
,所以复制/移动构造函数不可用。为什么编译器不报错?