如果我在我的库中添加移动构造函数(或移动赋值运算符),那么会破坏二进制兼容性吗?这种添加是否可能以任何方式破坏用户的代码?
class Foo {
public:
Foo();
Foo(Foo const&);
Foo& operator=(Foo const&);
// new methods:
Foo(Foo&&);
Foo& operator=(Foo&&);
};
如果我在我的库中添加移动构造函数(或移动赋值运算符),那么会破坏二进制兼容性吗?这种添加是否可能以任何方式破坏用户的代码?
class Foo {
public:
Foo();
Foo(Foo const&);
Foo& operator=(Foo const&);
// new methods:
Foo(Foo&&);
Foo& operator=(Foo&&);
};
它确实会破坏二进制兼容性:针对你的新库编译的代码无法与旧版本一起使用,因为链接时找不到移动构造函数。
另一个方向比较棘手。通常不是什么大问题,但通过SFINAE技巧,代码可能至少观察到新赋值运算符的存在,并且最终导致程序的某些部分认为该运算符存在,而其他部分则不认为。如果相同的代码被编译两次(在不同的翻译单元中进行的相同的模板实例化),这甚至可能导致ODR违规。而这些ODR违规可能再次导致链接时间错误。
template <typename T> T f(T& t) { return T(std::move(t)); }
假设二进制文件“A”使用你库的旧版本“C”来实例化 f<X>
,并得到复制构造函数。假设库“B”也实例化了带有你新库版本的f<X>
,并得到移动构造函数。那么当二进制文件“A”与库“B”链接时会发生什么?你不能在同一个程序中有多个f<X>
实例化,因此会选择一个版本,可能是二进制文件的版本。即使从库中调用该函数,也将调用该版本。 - user743382f
的移动效果,并且完全有权这样做。 - user743382