关于将const引用绑定到临时的子对象 [英] About binding a const reference to a sub-object of a temporary

查看:132
本文介绍了关于将const引用绑定到临时的子对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用类似

#include <iostream>

struct P {
    int x;
    P(int x) : x(x) {}
    ~P() { std::cout << "~P()\n"; }
};

int main() {
    auto const& x = P{10}.x;
    std::cout << "extract\n";
}

GCC列印〜P c $ c>,表示临时的生存期没有被引用延长。

GCC prints ~P() extract, indicating that the temporary's lifetime is not extended by the reference.

相反,Clang(IMO正确地)将临时的生命周期扩展到引用 x 的生命周期因此析构函数在 main 中的输出后称为

By contrast, Clang (IMO correctly) extends the lifetime of the temporary to the lifetime of the reference x and the destructor will be therefore called after the output in main.

请注意,GCC突然显示Clang的行为,而不是 int ,使用一些类类型(例如 string )。

Note that GCC suddenly shows Clang's behavior if we, instead of int, use some class type (e.g. string).

这是GCC中的错误还是标准允许的错误?

Is this a bug in GCC or something allowed by the standard?

推荐答案

CWG 1651 提供:


问题的解决 616 1213 ,使成员
访问或下标表达式的结果应用于prvalue xvalue,意味着
绑定对临时的子对象的引用不会
延长临时的生命周期。 12.2 [class.temporary]应该
修改以确保它。

The resolution of issues 616 and 1213, making the result of a member access or subscript expression applied to a prvalue an xvalue, means that binding a reference to such a subobject of a temporary does not extend the temporary's lifetime. 12.2 [class.temporary] should be revised to ensure that it does.

现在是只有普通价值被视为指临时性 - 因此 [class.temporary] / 5 第二个上下文是当引用绑定到临时。)不被认为适用。 Clang和GCC实际上没有实现问题616的解决方案。 center()。x 被视为prvalue由两者。我最好的猜测:

The status quo is that only prvalues are treated as referring to temporaries - thus [class.temporary]/5 ("The second context is when a reference is bound to a temporary.") is not considered applicable. Clang and GCC have not actually implemented issue 616's resolution, though. center().x is treated as a prvalue by both. My best guess:

  • GCC simply didn't react to any DRs yet, at all. It doesn't extend lifetime when using scalar subobjects, because those are not covered by [dcl.init.ref]/(5.2.1.1). So the complete temporary object doesn't need to live on (see aschelper's answer), and it doesn't, because the reference doesn't bind directly. If the subobject is of class or array type, the reference binds directly, and GCC extends the temporary's lifetime. This has been noted in DR 60297.

Clang已经识别成员访问权并实现了新生命期延期规则,甚至处理转换。从技术上讲,这与它处理值类别的方式不一致。

Clang recognizes member access and implemented the "new" lifetime extension rules already - it even handles casts. Technically speaking, this is not consistent with the way it handles value categories. However, it is more sensible and will be the correct behavior once the aforementioned DR is resolved.

因此,我认为这是正确的行为。说GCC是通过当前的措辞是正确的,但是当前的措辞是有缺陷和模糊的,并且Clang已经将待决的解决方案实施到DR 1651,这是 N3918 。本文非常清楚地说明了这个例子:

I'd therefore say that GCC is correct by current wording, but current wording is defective and vague, and Clang already implemented the pending resolution to DR 1651, which is N3918. This paper covers the example very clearly:


如果 E1 E2 不指定
位字段,则 E1.E2 是一个临时表达式。 p>

If E1 is a temporary expression and E2 does not designate a bit-field, then E1.E2 is a temporary expression.

center()是一个临时表达式,按照[expr。呼叫] / 11。因此,其在上述[class.temporary] / 5中的修改的措辞适用:

center() is a temporary expression as per the paper's wording for [expr.call]/11. Thus its modified wording in the aforementioned [class.temporary] /5 applies:


第二上下文是当引用不直接绑定8.5.3
dcl.init.ref)或使用临时表达式初始化(第5节)。 对应的临时
对象(如果有)在参考生命周期内仍然存在
,除了: [... inapplicable exceptions ...]

The second context is when a reference does not bind directly (8.5.3 dcl.init.ref) or is initialized with a temporary expression (clause 5). The corresponding temporary object (if any) persists for the lifetime of the reference except: [...inapplicable exceptions...]

Voilà,我们有终生延期。注意对应的临时对象不够清楚,提案推迟的原因之一;

Voilà, we have lifetime extension. Note that "the corresponding temporary object" is not clear enough, one of the reasons for the proposal's deferment; it will assuredly be adopted once it gets revised.


是xvalue(但不是位字段),类prvalue,数组prvalue 或函数lvalue和 cv1 T2 或[...]

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 […]

事实上,GCC完全尊重这一点,如果子对象有数组类型,则会延长生命周期。

Indeed, GCC respects this fully and will extend lifetime if the subobject has array type.

这篇关于关于将const引用绑定到临时的子对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆