【问题标题】:Can changing from private constructor/assignment operator to deleted break binary compatibility?可以从私有构造函数/赋值运算符更改为已删除破坏二进制兼容性吗?
【发布时间】:2020-12-02 15:41:38
【问题描述】:

使用 C++11。

我有一个班级,我想通过以下更改来清理一下:

来自

class MyClass {
public:
  // code
private:
  MyClass(const MyClass&);
  MyClass& operator=(const MyClass&);
  // members
};

收件人

class MyClass {
public:
  // code
  MyClass(const MyClass&) = delete;
  MyClass& operator=(const MyClass&) = delete;
private:
  // members
};

知道两者都是已声明但未定义,此更改会破坏二进制兼容性吗? 有什么改善吗?

【问题讨论】:

  • 我的经验是更改对象签名总是会破坏二进制兼容性。我总是认为你需要重建。不过,我不知道您要改进什么。我认为您不希望在任何情况下(即使是私下)使用任何一种复制方法,所以可能会这样做。
  • 唯一对标准给出的“二进制兼容性”的认可是单一定义规则,它描述了单独编译的代码共享数据类型的充分条件。这种变化确实打破了单一定义规则。以这种方式将不同的编译单元链接在一起是未定义的行为
  • 然而,虽然单一定义规则描述了充分条件,但在许多实际实现中,必要条件要弱得多。依赖比单一定义规则更弱的条件将使您的代码不可移植。
  • 我的目标是利用 C++11 特性提高源代码的清晰度和可读性,这些特性为我的代码增加了表现力,所有这些都不会破坏任何类型的兼容性。虽然人们可以期待一个私有复制构造函数的定义,但将其标记为删除对于不可复制的意图非常清楚。
  • @JosephLarson 这只是一个假设,但我希望如果在某处调用函数,更改函数签名会导致二进制不兼容。在这里,在这两种情况下,函数可能不会在生成的程序集中的任何地方调用(在第一种情况下会导致未定义的引用)。

标签: c++ c++11 binary-compatibility


【解决方案1】:

如果您从第一个版本切换到第二个版本,您可以访问、用户声明、删除的构造函数,这样的代码将在 C++11 中编译:

MyClass b{};

但如果你升级到 C++20,它不会。那可能不是你想要的。如果您坚持使用无法访问构造函数的第一个版本,b 的声明将不会在任何语言版本中编译,因此您至少不会遇到这个问题。

这是demo

【讨论】:

  • 迁移到 C++20 很有可能会破坏二进制兼容性,所以我想这不是问题
  • @A.Gille 够公平的。如果您进行过渡,我只是指出了一项潜在的重大变化。在升级到 C++20 之前,很可能还有其他一些影响你的东西。
  • 正如 OP 所说,以前的函数不是 declared but not defined,那么任何错误都会从链接阶段转移到编译阶段。这可能有助于大型项目。
  • @A.Gille 我稍微编辑了这个问题。编辑好吗?相信这并不能真正回答你的问题吗?
猜你喜欢
  • 2015-07-06
  • 1970-01-01
  • 1970-01-01
  • 2013-03-08
  • 1970-01-01
  • 2012-09-24
  • 2018-12-27
  • 1970-01-01
  • 2020-04-18
相关资源
最近更新 更多