如果我将移动构造函数(或移动赋值运算符)添加到我的库中,我是否会破坏二进制兼容性?这种添加能否以任何方式破坏用户的代码?
class Foo {
public:
Foo();
Foo(Foo const&);
Foo& operator=(Foo const&);
// new methods:
Foo(Foo&&);
Foo& operator=(Foo&&);
};
答案 0 :(得分:1)
在我看来,只要你不添加成员或虚函数,就不会对二进制兼容性产生任何影响,因为对象的布局不会改变。
如果一个组件(例如共享库,Windows上的.dll
或Linux上的.so
)使用旧版本的库,那么它将复制对象的所有实例(甚至是rvalues),而不管它是否是由使用新库的组件创建的(反之亦然)。
只要使用移动语义来提高性能,因此生成的移动对象与复制对象的行为相同就应该没有问题。唯一的区别是由于对内存[de]分配和副本(等)的调用次数减少而导致性能提高。如果使用移动操作来制作不同的语义(移动的对象与复制的对象不同),那么所有的赌注都会关闭,但我不认为有人会故意这样做(除了工作安全性之外)。
只要对象的二进制布局没有改变,我就不会看到如何引入任何破损。
答案 1 :(得分:1)
它肯定会在一个方向上打破二进制兼容性:针对您的新库编译的代码无法与旧版本一起使用,因为链接时将找不到移动构造函数。
另一个方向比较棘手。它通常不是什么大问题,但代码可能至少观察到新的赋值运算符与SFINAE技巧的存在,并且最终得到一个程序,其中一些部分认为运算符存在,并且其他部分没有。如果相同的代码被编译两次(在不同的翻译单元中进行相同的模板实例化),这甚至可能导致ODR违规。而那些ODR违规可能会再次导致链接时错误。