列出与引用一起使用,用作成员时更改行为 [英] List using with references, changes behavior when used as a member

查看:79
本文介绍了列出与引用一起使用,用作成员时更改行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对此问题进行实验/ answer https://stackoverflow.com/a/50649120/225186 我给出了看起来成为实现循环列表的合法递归自引用类:

Experimenting with this question/answer https://stackoverflow.com/a/50649120/225186 I produced what seems to be a legal recursive self referential class that implements a circular list:

struct node{
    int val;
    node const& next;
};

int main(){
    node s{3, {4, s}};

    assert(s.val == 3);
    assert(s.next.val == 4);
    assert(&s.next.next == &s);
    assert(s.next.next.val == 3);
}

但是,当我尝试将其作为较大类的成员时,

However, when I try put this as a member of a larger class I get a warning from the compiler and the behavior changes.

struct A{
    node n;
    int i;
    A(int a, int b) : n{a, {b, n}}{} // warning here, also tried n{a, node{b, n}}
};

int main(){
    A a(3, 4);
    assert( a.n.val == 3 );
    assert(&(a.n.next.next) == &(a.n)); // this assert fail and 
    assert( a.n.next.val == 4 ); // segmentation fault here
}

我得到的警告是 gcc:警告:临时绑定到'A :: n'的操作只会持续到构造函数退出[-Wextra] 为止。
我不认为该警告是正确的,但是它与以后的运行时错误一致。

The warning I get is gcc: warning: a temporary bound to ‘A::n’ only persists until the constructor exits [-Wextra]. I don't believe that the warning is correct, however it is consistent with the later runtime error.

我承认该类是非常规的,但是,怎么可能是一个班级改变了班级内部的行为?

I admit that the class is non-conventional, however, how can it be that a class that it changes behavior inside a class?

我错过了什么吗?

推荐答案

聚合初始化允许将引用绑定到临时对象(,这会导致生命周期延长)。您的第一个示例是聚合初始化,因为 node 是一个聚合。

Aggregate initialization allows binding references to temporaries (and this causes lifetime extension). Your first example is aggregate initialization because node is an aggregate.

但是,在构造函数成员初始化器列表中,它的格式不正确,无法将引用绑定到临时(C ++ 17 class.base.init / 11)。这是因为在这种情况下不会延长生命周期,并且允许它不可避免地会产生悬挂的参考。在第二个示例中, node 不是聚合,因为它具有用户提供的构造函数。

However, in a constructor member initializer list, it is ill-formed to bind a reference to a temporary (C++17 class.base.init/11). This is because there is no lifetime extension in that situation , and allowing it would inevitably produce a dangling reference. In the second example node is not an aggregate because it has a user-provided constructor.

这篇关于列出与引用一起使用,用作成员时更改行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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