【问题标题】:C++ bind reference member to constructor parameterC++ 将引用成员绑定到构造函数参数
【发布时间】:2017-08-25 11:39:28
【问题描述】:

在 gcc 8 上运行以下代码时(https://wandbox.org/,使用“g++ prog.cc -Wall -Wextra -std=c++1z”):

#include <iostream>

class B{
public:
    B(): copy(false){ std::cout << "B-constructed" << std::endl;}
    B(const B& b): copy(true){ std::cout << "B-copy-constructed" << std::endl; }
    ~B(){ std::cout << (copy?"B-destructed":"B-(copy)-destructed") << std::endl;}

    bool copy;
};

class A{
public:
    A(B b): bref(b){std::cout << "A-constructed" << std::endl;}
    ~A() {std::cout << "A-destructed" << std::endl;}
    B &bref;
};


void f(){
    B b;
    A a(b);

    std::cout << "f over" << std::endl;
}

int main()
{
    f();

    std::cout << "main over" << std::endl;
    return 0;
}

产生以下输出:

B-constructed
B-copy-constructed
A-constructed
B-destructed
f over
A-destructed
B-(copy)-destructed
main over

对象销毁的顺序似乎不寻常。就好像构造函数的参数的生命周期被延长了。标准是否说明了将成员引用绑定到构造函数参数?

我认为标准中的这句话不适用,因为参数不是临时对象(但是我不知道“临时表达式”的定义):

绑定到 mem-initializer 中的引用成员的临时表达式格式不正确。 [ 例子:

结构 A {

A() : v(42) { } // 错误

const int& v;

};

——结束示例]

【问题讨论】:

  • 你把~B中的字符串弄混了:如果是副本,说它是正常破坏的,如果不是,说它是复制破坏的
  • 那么问题是什么?在修复之后,您认为构建/销毁的顺序有什么问题?
  • 现在订单看起来不错。然而,剩下的问题是标准是否说明了将成员引用绑定到构造函数参数。
  • eel.is/c++draft/basic.life#7 是否解释了这种行为(绑定到生命周期已结束的对象的引用)?

标签: c++ class oop reference lifetime


【解决方案1】:

你的析构函数有一个逻辑错误,因为当copy 错误时,你打印出一个副本被破坏。

改变这个:

~B(){ std::cout << (copy?"B-destructed":"B-(copy)-destructed") << std::endl;}

到这里:

~B(){ std::cout << (copy?"B-(copy)-destructed":"B-destructed") << std::endl;}

现在输出:

B-constructed
B-copy-constructed
A-constructed
B-(copy)-destructed
f over
A-destructed
B-destructed
main over

简洁明了 (Order of member constructor and destructor calls)。


标准是否说明了将成员引用绑定到构造函数参数?

类似地,在对象的生命周期开始之前但在对象的生命周期开始之后 对象将占用的存储空间已被分配,或者在 对象的生命周期已经结束并且在存储之前 被占用的对象被重用或释放,任何引用 可以使用原始对象,但只能以有限的方式使用。对于一个对象 正在建设或销毁,请参阅 [class.cdtor]。否则,这样的 一个glvalue是指分配的存储 ([basic.stc.dynamic.deallocation]),并使用 不依赖于其值的 glvalue 是明确定义的。

Source

【讨论】:

  • 我为我的错误道歉。是的,现在的顺序似乎是正确的。但是,标准是否提到了将成员引用绑定到构造函数参数的任何内容?
  • 当然,没问题。我更正了我的问题,因为在看到您的答案之前收到了来自 @king_nak 的评论。
  • 我发现了这个:eel.is/c++draft/basic.life#7。我认为它解释了引用生命周期已结束的对象时会发生什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多