为什么应该拷贝构造函数有时被声明为非显式的

我无法理解关于内联和客户二进制兼容性的句子。 有人可以解释吗?

C ++常见问题解答Cline,Lomow:

当编译器合成复制构造函数时,它使它们内联。 如果你的类暴露给你的客户(例如,如果你的客户#包括你的头文件而不是仅仅使用从你的类构建的可执行文件),你的内联代码将被复制到你的客户可执行文件中。 如果您的客户希望在头文件发布之间保持二进制兼容性,则不得更改客户可见的内联函数。 因此,您需要一个显式的非内联版本的复制构造函数,它将直接由客户使用。


动态库( .dll.so )的二进制兼容性通常非常重要。

例如,您不希望在操作系统上重新编译一半软件,因为您更新了一些低级库,所有内容都以不兼容的方式使用(并考虑安全更新的频繁程度)。 即使您想要,您甚至可能甚至没有所需的所有源代码。

要使动态库的更新兼容并且实际上具有效果,实质上不能在公共头文件中更改任何内容,因为所有内容都直接编译到其他二进制文件中(即使在C代码中,这通常也可以包含结构大小和成员布局,显然你不能删除或更改任何函数声明)。

除了C问题之外,C ++还引入了更多的内容(虚拟函数的顺序,继承的工作原理等),因此可以想象,您可能会做一些更改自动生成的C ++构造函数,复制,析构函数等,同时保持兼容性。 如果将它们与类/结构一起“内联”定义,而不是明确地在源代码中定义,那么它们将直接被链接到动态库并使用这些自动生成的函数的其他应用程序/库包含,并且它们不会让你的改变版本(你可能甚至没有意识到改变了!)。


答案是这样的:如果涉及函数的签名没有改变,那么“重建”程序意味着目标文件必须重新链接。 你不需要再编译它们。

本文描述了在GNU / Linux系统上用C ++实现的共享库二进制兼容性的概念。 在编写库时,这个链接也可以帮助您理解在执行二进制兼容性时应做的和不该做的事情。

为什么我们没有虚拟构造函数的概念也与此有关。

您可能对验证两个给定版本的兼容性的工具感兴趣:用于Linux的abi-compliance-checker。


它指的是库的二进制发行版和库中的标题更改之间可能发生的问题。 有一些变化是二进制兼容的,某些变化不是。 内联函数(如内联复制构造函数)的更改不是二进制兼容的,并且需要重新编译使用者代码。

你一直在单个项目中看到这一点。 如果更改a.cpp则不必重新编译包含a.hpp所有文件。 但是,如果您更改头中的接口,那么通常需要重新编译该头的任何使用者。 这与使用共享库的情况类似。

当需要更改二进制库的实现而不更改其接口时,保持二进制兼容性非常有用。 这对于修复错误很有用。

比如说一个程序使用liba作为共享库。 如果liba包含它暴露的类的方法中的错误,那么它可以更改内部实现并重新编译共享库,并且程序可以使用该liba的新二进制版本而不用重新编译它。 但是,如果liba更改公共契约(例如实现内联方法)或将内联方法移到外部声明,那么它将打破应用程序二进制接口(ABI),并且必须重新编译使用程序以使用新的二进制版本的liba

链接地址: http://www.djcxy.com/p/40271.html

上一篇: Why should copy constructors be sometimes declared explicitly non

下一篇: How do I install an older release of Visual Studio 2017?