警告:X 的默认移动赋值运算符将多次移动分配虚拟基类 Y

2024-01-07

在 C++11 下测试库时,我在 Clang 下收到警告。我以前从未遇到过这个警告,并且搜索并没有提供太多的阅读和研究方式。

该警告如下所示,它似乎与多重继承和公共基类有关。但我不清楚触发警告的细节或我应该采取什么措施来解决它。

我的第一个问题是,这是一个需要解决的问题吗? Or 这仅仅是效率问题吗?

我的第二个问题是(如果需要的话),我该如何解决该警告? Or 有哪些选项可用于补救?


以下是一些附加信息:

  • 编译器:Apple LLVM 6.0版(clang-600.0.57)(基于LLVM 3.5svn)
  • g++ -DDEBUG -g2 -O2 -std=c++11 -fPIC -march=native -pipe -c test.cpp

在 Stack Overflow 上还审查了以下内容,但我不清楚它们的交叉点:

  • C++11 中的“三法则”变成了“五法则”? https://stackoverflow.com/q/4782757

图书馆,Crypto++ https://www.cryptopp.com/,也大量使用奇怪的重复模板模式 https://stackoverflow.com/q/4173254/608639用于编译时多态性。


头文件 http://www.cryptopp.com/docs/ref/rsa_8h_source.html可以在线获取,这是实际的警告:

g++ -DDEBUG -g2 -O2 -std=c++11  -Wno-deprecated-declarations -fPIC -march=native -pipe -c rsa.cpp
In file included from rsa.cpp:4:
In file included from ./rsa.h:12:
./pubkey.h:635:26: warning: defaulted move assignment operator of 'InvertibleRSAFunction' will move assign virtual base class 'CryptoMaterial' multiple times [-Wmultiple-move-vbase]
class CRYPTOPP_NO_VTABLE TF_ObjectImpl : public TF_ObjectImplBase<BASE, SCHEME_OPTIONS, KEY_CLASS>
                         ^
./rsa.h:57:44: note: 'CryptoMaterial' is a virtual base class of base class 'CryptoPP::RSAFunction' declared here
class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey
                                           ^~~~~~~~~~~~~~~~~~
./rsa.h:57:96: note: 'CryptoMaterial' is a virtual base class of base class 'CryptoPP::PKCS8PrivateKey' declared here
class CRYPTOPP_DLL InvertibleRSAFunction : public RSAFunction, public TrapdoorFunctionInverse, public PKCS8PrivateKey
                                                                                               ^
1 warning generated.

我很抱歉没有减少它。我不知道如何减少它并抓住警告/投诉的本质。


该警告对我来说似乎是不言自明的,它告诉您移动分配派生类型将导致移动分配基数两次。

减少它很简单,只需使用虚拟基和两个路径来创建继承层次结构即可:

#include <stdio.h>

struct V {
    V& operator=(V&&) { puts("moved"); return *this; }
};

struct A : virtual V { };

struct B : virtual V { };

struct C : A, B { };

int main() {
    C c;
    c = C{};
}

这将打印"moved"两次,因为每个的隐式移动赋值运算符A, B and C将进行成员分配,这意味着两者A::operator=(A&&) and B::operator=(B&&)将分配基类。正如艾伦所说,这是该标准的有效实施。 (该标准指定在构造时只有最派生的类型才会构造虚拟基,但它对赋值没有相同的要求)。

这不是特定于移动分配,将基类更改为仅支持复制分配而不支持移动分配将打印"copied" twice:

struct V {
    V& operator=(const V&) { puts("copied"); return *this; }
};

发生这种情况的原因完全相同A::operator=(A&&) and B::operator=(B&&)将分配基类。编译器不会针对这种情况发出警告,因为执行两次复制分配(可能)只是次优,而不是错误。对于移动分配,它可能会丢失数据。

如果您的虚拟基础实际上没有任何需要复制或移动的数据,或者仅具有可轻松复制的数据成员,则使其仅支持复制而不移动将抑制警告:

struct V {
    V& operator=(const V&) = default;
};

这个复制赋值运算符仍然会被调用两次,但由于它不执行任何操作,所以没有问题。什么事都不做两次,还是什么事都没有。

(GCC 在这里似乎比 Clang 聪明一点,它不会警告虚拟基地的移动赋值运算符在微不足道的情况下被调用两次,因为微不足道的移动相当于复制,因此不太可能成为问题)。

如果虚拟基础确实有需要在分配时复制的数据,那么使其进行复制而不是移动可能仍然是一个不错的选择,但这取决于类型和用途。您可能需要在层次结构的每个级别显式定义复制和移动分配。虚拟基地很棘手并且很难正确使用,尤其是在面对复制或移动时。将具有虚拟基的类型视为可以轻松复制和移动的值类型可能是一个设计错误。

iostreams 层次结构使用虚拟基,但做得很仔细且正确。 iostream 类型是不可复制的,只能移动,派生类型显式定义移动赋值以确保basic_ios<>基类仅更新一次。具体来说,basic_iostream::operator=(basic_iostream&&)仅运行于basic_istream基础,而不是basic_ostream一。上面的例子的等价物是:

struct C : A, B {
     C& operator=(C&& c) {
         static_cast<A&>(*this) = static_cast<A&&>(c);
         return *this;
     }
};

Iostream 根本不可复制,直到 C++11,此时右值引用和移动语义使得使用有用的语义成为可能。如果您的类在 C++03 中始终是可复制的,那么它可能已经是一个有问题的设计,本应是不可复制的,或者仔细编写了复制操作而不是隐式定义的操作。

简而言之,任何时候你有虚拟基地,你都需要非常仔细地考虑构建、分配和销毁如何工作,以及复制和分配对于该类型是否有意义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

警告:X 的默认移动赋值运算符将多次移动分配虚拟基类 Y 的相关文章

  • 检测wlan是否关闭

    任何人都可以给我一个提示 如何在 Windows Phone 上以编程方式检测 C 8 1 应用程序 不是 8 0 是否启用 禁用 WLAN 我不想更改这些设置 只是需要知道 该解决方案是一个 Windows 8 1 通用应用程序 Wind
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • linq 中使用字符串数组 c# 的 'orderby'

    假设我有一个这样的方法定义 public CustomerOrderData GetCustomerOrderData string CustomerIDs var query from a in db Customer join b in
  • 运行需要 MySql.Data 的内置 .NET 应用程序

    我在运行我编写的内置 NET 应用程序时遇到问题 我的应用程序使用最新的 MySql 连接器 该连接器安装在我的系统上 当我尝试将其添加为引用时 该连接器显示为 NET 4 Framwork 组件 当我在环境中以调试模式运行应用程序时 一切
  • 是否存在指向不同类型的指针具有不同大小的平台?

    C 标准允许指向不同类型的指针具有不同的大小 例如sizeof char sizeof int 是允许的 但是 它确实要求如果将指针转换为void 然后转换回其原始类型 它必须与其原始值进行比较 因此 从逻辑上来说 sizeof void
  • 为什么'enable_if'不能用于禁用这里声明

    include
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 将表(行)与 OpenXML SDK 2.5 保持在一起

    我想在 Word 文档中生成多个表 每行 2 行 但我想将这两行保留在一起 如果可能的话 new KeepNext 第一行不起作用 new KeepNext 第一行的最后一段不起作用 new CantSplit 放在桌子上不起作用 在所有情
  • 获取 boost Spirit 语法中的当前行

    我正在尝试使用 boostspirit 获取正在解析的文件的当前行 我创建了一个语法类和结构来解析我的命令 我还想跟踪在哪一行找到命令并将其解析到我的结构中 我将 istream 文件迭代器包装在 multi pass 迭代器中 然后将其包
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 引用/指针失效到底是什么?

    我找不到任何定义指针 引用无效在标准中 我问这个问题是因为我刚刚发现 C 11 禁止字符串的写时复制 COW 据我了解 如果应用了 COW 那么p仍然是一个有效的指针并且r以下命令后的有效参考 std string s abc std st
  • 英文日期差异

    接近重复 如何计算相对时间 https stackoverflow com questions 11 how do i calculate relative time 如何在 C 中计算某人的年龄 https stackoverflow c
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 从浏览器访问本地文件?

    您好 我想从浏览器访问系统的本地文件 由于涉及大量安全检查 是否可以通过某种方式实现这一目标 或使用 ActiveX 或 Java Applet 的任何其他工作环境 请帮帮我 要通过浏览器访问本地文件 您可以使用签名的 Java Apple
  • 在 OpenGL 中渲染纹理 1 到 1

    所以我想做的是使用 OpenGL 和 C 将纹理渲染到平面上 作为显示图像的一种方式 但是我需要确保在渲染纹理时没有对纹理进行任何处理 抗锯齿 插值 平滑 模糊等 这是 OpenGL 处理渲染纹理的默认方式吗 或者是否需要设置一些标志才能禁
  • 如何停止无限循环?

    我正在编写一个程序 该程序将计算三角形或正方形的面积 然后提示用户是否希望计算另一个 我的代码已经运行到可以计算任一形状的面积的程度 但随后不再继续执行代码的其余部分 例如 如果选择了正方形 则计算面积 然后返回到正方形边长的提示 我假设这
  • 如何调试 .NET 运行时中的内部错误?

    我正在尝试调试一些处理大文件的工作 代码本身works 但 NET 运行时本身会报告零星错误 对于上下文 这里的处理是一个 1 5GB 文件 仅加载到内存中一次 在循环中处理和释放 故意尝试重现此否则不可预测的错误 我的测试片段基本上是 t
  • 需要提取字符串中点后的最后一个数字,如“7.8.9.1.5.1.100”

    我需要提取 C 字符串中最后一个点后面的最后一个数字 例如 7 8 9 1 5 1 100 并将其存储在整数中 Added 该字符串也可以是 7 8 9 1 5 1 1 或 7 8 9 1 5 1 0 我还想验证它在最后一个点之前恰好是 7
  • 使用 using 声明时,非限定名称查找如何工作?

    根据 C 标准 这是格式错误还是格式良好 namespace M struct i namespace N static int i 1 using M i using N i int main sizeof i Clang 拒绝它 GCC
  • 结构化绑定的用例有哪些?

    C 17 标准引入了新的结构化绑定 http en cppreference com w cpp language structured binding功能 最初是proposed http www open std org jtc1 sc

随机推荐

  • 嗅探并显示 UTF-8 格式的 TCP 数据包

    我正在尝试使用 tcpdump 来显示在我的网络上流动的 tcp 数据包的内容 我有类似的东西 tcpdump i wlan0 l A A 选项将内容显示为 ASCII 文本 但我的文本似乎是 UTF 8 有没有办法使用 tcpdump 正
  • 有没有更简单的方法在Matlab中构造Mandelbrot集?

    下面显示的代码用于绘制曼德尔布罗特集 http en wikipedia org wiki Mandelbrot set 我认为我的代码对于构造有点冗余Matrix M In Python我知道有一种干净的方法可以做到这一点 M mande
  • 日期时间向上和向下舍入

    我一直在寻找合适的舍入机制 但我发现似乎没有什么正是我所需要的 我需要分别向上舍入和向下舍入 并且还需要在已经四舍五入的情况下考虑情况 我需要进行以下舍入 5 00 gt RoundDown gt 5 00 5 04 gt RoundDow
  • 使用 powerlaw 包对截止分布进行幂律拟合

    我目前正在尝试找到一种方法来计算 MLE 截止分布的幂律拟合 分布如下 正如您所看到的 我能够分别拟合整个分布 幂律拟合 和下限 exp fit 我没能弄清楚的是如何拟合分布的上限 例如 8 有什么办法可以做到这一点poweRlaw包还是任
  • 如何使用 Docker API Python 客户端构建镜像?

    我刚刚启动了 Docker Api 并探索了各个部分 但是我一直坚持使用 python 客户端使用 docker api 构建图像 实际上我无法理解如何为 docker 设置各种所需的参数客户端 images build 方法 请帮帮我 提
  • R:rvest - 不是正确的 UTF-8,表明编码?

    我正在尝试 Hadley Wickham 的 新 Rvest 套餐 我过去用过它 所以我希望一切都会顺利进行 但是 我一直看到这个错误 gt TV Audio Video Marca lt read html page source 1 e
  • 在Python中高效地搜索字符串列表中的字符串列表

    我有一个字符串列表和一个字符串列表 例如 L1 cat dog apple orange green red L2 cat red 如果 L1 i 包含 L2 中的任何项目 我需要放置这些对 用于在图中创建边 就像 在我的例子中 我需要这些
  • Hadoop 中的作业和任务调度

    当我阅读延迟公平调度时 我对 Hadoop 中的术语 作业调度 和 任务调度 有点困惑在这张幻灯片中 https people csail mit edu matei talks 2010 eurosys delaysched pdf 如果
  • JavaScript 内部原理:事件循环以什么间隔运行?

    这是一个关于 JavaScript 内部结构的问题 假设我有 10 个异步任务 全部需要 x 秒才能运行 在等待响应时 脚本处于空闲状态 JavaScript 引擎在后台询问 任务队列中是否有任何内容 据我了解 这是一个循环 因此 事件循环
  • 程序员应该使用STL还是自己编写代码? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 合并表单和字段集不起作用?

    I ve a
  • 如何获得带有“下一步”、“上一步”和“完成”按钮的键盘?

    我想要一个上面有 下一步 上一步 和 完成 按钮的键盘 我在很多应用程序中都看到过这一点 尤其是需要填写表格的地方 我想实现类似于上面键盘的东西 我怎样才能得到它 你会找到答案这另一篇文章 https stackoverflow com q
  • 如何从nodejs中的phantomjs stdout读取图像来为其提供服务?

    我可能遗漏了一些细节 因为光栅化脚本独立工作得很好 但到目前为止我还没有成功地从 NodeJS 读取它的输出 这是 NodeJS 部分 var http require http var qs require querystring var
  • Django 形成动态让作者作为模型表单中的登录用户

    我正在尝试制作一些表单 允许用户添加一些对象 删除它们或编辑 但我一直坚持模型作者之类的内容 假设我们得到了带有场的模型镜头 author models ForeignKey settings AUTH USER MODEL on dele
  • 如何最小起订量索引属性

    我正在尝试模拟对索引属性的调用 IE 我想最小起订量以下 object result myDictionaryCollection SomeKeyValue 还有设置器值 myDictionaryCollection SomeKeyValu
  • 在.NET中编写虚拟打印机[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我希望创建一个虚拟打印机 将数据传递到我的 NET 应用程序 然后我想创建一个安装程序来安装打印机和
  • 如何在 Weka 中计算聚类评估的准确性

    我们如何使用 Weka 计算集群的准确性 我可以使用这个公式 Accuracy A tp tn Total samples 但我如何知道Weka工具中实验输出的真阳性 假阳性 真阴性和假阴性是什么 Weka中有几种不同的聚类模式 使用训练集
  • 为什么我的Python在尝试运行turtle模块中的turtle.tracer()方法时不断崩溃?

    我正在使用海龟模块编写贪吃蛇游戏 但是当我将这一行添加到我的代码中时 海龟屏幕和 python 崩溃了 turtle tracer 0 有人可以帮助我完成游戏吗 多谢 my code from turtle import Turtle Sc
  • 根据 Scala 和 Spark 中的频率替换二元组

    我想用这种模式替换所有频率计数大于阈值的二元组 word1 concat concat word2 我已经尝试过 import org apache spark SparkConf SparkContext object replace d
  • 警告:X 的默认移动赋值运算符将多次移动分配虚拟基类 Y

    在 C 11 下测试库时 我在 Clang 下收到警告 我以前从未遇到过这个警告 并且搜索并没有提供太多的阅读和研究方式 该警告如下所示 它似乎与多重继承和公共基类有关 但我不清楚触发警告的细节或我应该采取什么措施来解决它 我的第一个问题是