You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构造含std::shared_ptr成员的结构体的std::optional实例

核心结论

你不需要手动编写额外的构造函数,本次报错和std::make_optional、类的构造函数都没有关系,是类B的赋值能力缺失导致的。

报错根因
  1. 你的类B定义了const std::shared_ptr<A> a成员:const成员初始化后不可修改,因此编译器会自动删除类B的拷贝赋值运算符、移动赋值运算符。
  2. 代码中b = std::make_optional<B>(a)是std::optional的移动赋值操作,std::optional的移动赋值运算符要求内部存储的类型支持移动/拷贝赋值,否则该运算符也会被隐式删除,因此触发编译报错。
可行解决方法

根据你的业务场景可任选以下方案:

方案1:直接初始化std::optional,避免赋值操作

不需要先声明空optional再赋值,直接在声明时完成初始化,不会触发optional的赋值运算符,不需要修改类B的定义:

#include <optional>
#include <memory>
class A
{
public:
 A(int v):
  val{v}
  {}
 int val;   
};

class B
{
public:
 B(std::shared_ptr<A>& a):
   a{a}
 {}
 
 const std::shared_ptr<A> a;   
};


int main()
{
  std::shared_ptr<A> a = std::make_shared<A>(3);
  std::optional<B> b = std::make_optional<B>(a); // 直接初始化,无赋值操作
}

方案2:去掉成员变量的const修饰

如果你确实需要先声明空optional再赋值,移除类B成员a的const限定即可让编译器自动生成默认的移动赋值运算符:

class B
{
public:
 B(std::shared_ptr<A>& a):
   a{a}
 {}
 std::shared_ptr<A> a; // 移除const修饰
};

方案3:手动实现赋值运算符(不推荐)

如果必须保留成员的const属性且需要支持赋值操作,只能手动实现类B的赋值运算符,该方案违背const成员的语义,不推荐使用。


内容的提问来源于stack exchange,提问作者cjds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 19:18:00