【发布时间】:2026-02-04 00:05:01
【问题描述】:
以下代码-sn-p 似乎有效:
#include <iostream>
class Filling{
public:
const int num;
Filling(int num_)
: num(num_)
{ }
};
class Nougat{
public:
Nougat(const Filling& filling)
: reference(filling)
{ }
const Filling& get_filling() const{ return reference; }
private:
const Filling& reference;
};
class Wrapper{
public:
Wrapper(const Nougat& nougat)
: reference(nougat)
{ }
const Nougat& get_nougat() const{ return reference; };
private:
const Nougat& reference;
};
int main(){
Filling filling(3);
Wrapper wrap(filling); /*(0)*/
std::cout << wrap.get_nougat().get_filling().num << std::endl;
}
虽然初始化不正确(在/*(0)*/),因为Wrapper 类应该接受Nougat 类,而是给它一个Filling 类。
由于构造函数需要引用,我相信编译器正在从构造函数参数创建一个临时的Nougat 类,然后将其传递给初始化Wrapper 类。
从临时获取引用会导致未定义的行为。
这是真的发生了吗?
如果是这样,这段代码如何编译?
【问题讨论】:
-
Nougat来自Filling&的构造函数不是explicit,因此可用于隐式转换。Wrapper wrap(filling);被解释为Wrapper wrap(Nougat(filling));,创建一个临时的Nougat对象并将其传递给Wrapper。然后临时对象被销毁,给wrap留下一个悬空引用。随后使用该引用的尝试表现出未定义的行为。 “似乎有效”是未定义行为的一种可能表现形式。 -
我添加了显式关键字:
explicit Wrapper(const Nougat& nougat) ...,它仍然可以编译... -
可以用“如何禁止这种隐式行为”来扩展这个问题吗?
-
用于隐式转换的是
Nougat构造函数,而不是Wrapper构造函数。
标签: c++ reference initialization