C++ 在构造函数中用表达式初始化引用

标签 c++

考虑以下 C++ 类:

// An abstract fruit that can be sliced
class AbstractFruit
{
public:
  virtual void Slice() = 0;
};

// A lemon (concrete implementation of AbstractFruit)
class Lemon : public AbstractFruit
{
int size; // small medium large

public:
  Lemon(int size) : size(size) {}
  virtual void Slice() override { /* slice it */ }
};

// A pie uses a fruit reference
class Pie
{
  AbstractFruit& fruit;

public:
  Pie(AbstractFruit& fruit) : fruit(fruit) {}  
};

一切正常。

出于向后兼容的原因,Pie API 需要有一个创建柠檬派的构造函数:

Pie(int size) : fruit(Lemon(size)) {}

这行不通。据我所知,我正在构造函数的参数列表中创建一个新的 Lemon 实例,并用它初始化水果引用。但是,Lemon 实例在那之后立即被销毁,留下 fruit 引用指向一个被销毁的对象。

完成这项工作的最佳方法是什么?

我知道我可以将 Pie 切换为使用指针而不是引用,但我想尽可能使用引用。

最佳答案

如果 Pie 对象的大小不重要,一种可能的解决方案是让 Pie 管理可选的 Lemon:

class Pie
{
    std::optional<Lemon> lemon_;
    AbstractFruit& fruit_;

public:
    Pie(AbstractFruit& fruit) : fruit_(fruit) {}
    Pie(int size) : lemon_(size), fruit_(*lemon_) {}
};

std::optional 是可选的,std::unique_ptr 可以代替:

class Pie
{
    std::unique_ptr<Lemon> lemon_;
    AbstractFruit& fruit_;

public:
    Pie(AbstractFruit& fruit) : fruit_(fruit) {}
    Pie(int size) : lemon_(std::make_unique<Lemon>(size)), fruit_(*lemon_) {}
};

在第一种情况下,Lemon 将存储在 Pie 本身中,在第二种情况下,Lemon 将分配在堆上,并且Pie 将只存储指向它的指针。如果 Lemon 尺寸较小 (<= sizeof(void*)),std::optional 是更好的选择。

注意成员是initialized in order of declaration in the class ,这就是为什么 lemon_ 声明应该在 fruit_ 声明之前。

关于C++ 在构造函数中用表达式初始化引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58888943/

相关文章:

c++ - 如何在 Windows 7 平板设备中使用 C++ 调出屏幕键盘?

c++ - 在一行上声明多个对象指针会导致编译器错误

c# - 调试底层 C++ DLL 中的问题

c++ - 如何将 MPI 与 QT 一起使用?

c++ - boost log - 处理断电情况

c++ - 如何在 Qt C++ 中为数组动态分配内存?

c++ - Windows 加密 API 是否故意在调试器附加到进程的情况下运行得更慢?

python - 使用非 Qt 从 Qt QJsonDocument::toBinaryData 读取二进制 Json?

c++ - 协变虚函数和智能指针

c++ - 在linux库中查找静态函数地址