【问题标题】:Is std::string header only in Visual Studio?std::string 标头是否仅在 Visual Studio 中?
【发布时间】:2019-11-09 18:10:24
【问题描述】:

看起来std::stringCommunity/VC/Tools/MSVC/?/include/xstring 处的仅标头文件,并且所有生成的代码都应包含在构建目标中。

如果我是对的,微软如何保证下一个 Visual Studio 版本不会改变xstringstd::string 内部结构?

更新 1:

我对这个问题投了很多反对票,所以让我解释一下为什么我决定问这个问题。

我遇到了奇怪的崩溃,我不明白为什么会这样。 我使用最新的 Qt 5.13.0 (MSVC2017_x64),还有一些用 Visual Studio 2017 编译的外部库。都有/MDd,我用dumpbin util检查了这个。

当我尝试运行任何调用 Qt 库和 std::string 的代码时,我得到了错误的结果(并最终崩溃)。

这是一个非常简单的例子:

#include <QApplication.h>

int main(int argc, char** argv) {
    QString s1("Test");
    std::string s2 = s1.toStdString(); // here we have s2 variable with wrong internal structure
    return 0;
}

我的想法是 QtCore DLL 库的 std::string 内部结构与 Visual Studio 2017 中的 std::string 不兼容。但是 Qt 是使用 Visual Studio 2017 创建的(可能与我当前的 Visual Studio 不同,因为有几个次要版本),所以我决定在这里询问它们是否兼容。

更新 2:

问题出在_ITERATOR_DEBUG_LEVEL。看起来 Qt 是用 2 级编译的,而我所有的外部库和应用程序都是用 0 级编译的。

此选项会影响许多 C++ 标准库类的内部结构并引入此类副作用。因此,当我们在toStdString() 内部并创建std::string 时,我们有2 级和1 个内部结构。当我们在应用程序代码中时,我们有级别 0 和另一个内部结构。我们将具有一种内部结构的对象分配给具有另一种内部结构的对象。

不管怎样,现在我对一些内部结构有了更好的了解。

【问题讨论】:

  • 您应该依赖 ISO C++ 标准所说的 std::string 应该是什么样的。 (如果你不想阅读标准,this 应该足够好了)
  • 你为什么在乎?
  • 很多反对票,但我可以说出我为什么有趣。成像我们使用 Visual Studio 14 将一些代码编译到 DLL 库中,我们使用std::string。现在我们想将此库与 Visual Studio 15 代码一起使用,并且在 xstring 文件中进行了更改。我们如何保证如果我们从该库中调用函数并将结果分配给输出代码中的字符串,它将起作用?
  • How we could guaranty that if we call function from that library and assign result to string in out code it will work? - 这应该是问题本身,您的实际问题类似于“std::string 对象是否保证在不同版本的 VS 之间是二进制兼容的?” (而不是暗示您指望代码的特定实现)。您甚至可能想删除它并重试。
  • 老实说,我第一次读这个问题的印象是你不知道 C++ 标准和 Visual Studio 之间的区别。但是,如果您改写它以阐明您正在寻找什么(即二进制兼容性、构建系统可移植性、通过 Visual Studio 版本的解决方案文件的稳定性),这将立即成为一个更有趣的问题。

标签: c++ qt visual-c++


【解决方案1】:

微软如何保证下一个 Visual Studio 版本不会改变 xstring 和 std::string 内部结构?

因为他们决定保证或不保证。

例如,Visual Studio 2015 to 2019 are binary compatible

这是一个决定,要这样做。结果,如果你说的是真的,那么std::string 在那个平台上的一些实现细节被冻结了。这对图书馆来说并不罕见。 libstdc++'s std::list::size was non-compliant to C++11 for many years,因为他们无法在不破坏二进制兼容性的情况下添加所需的成员变量。

简而言之,这基本上是一个项目管理决策,如果他们以破坏事物的方式更改标题,他们会告诉您二进制兼容性已被破坏,您需要相应地重建和重新链接事物。

至于您的 Qt 问题,它确实闻起来 像二进制兼容性问题。但是您说 Qt 和您的应用程序都使用 /MDd 在 Visual Studio 2017 中构建,这似乎排除了这种可能性。我会向 Qt 社区寻求进一步的帮助,可能会提供更多关于您的环境以及您从何处获得 Qt 的信息。还要确保您使用的是预期的 Qt 版本——也许有多个安装?哪个在您的包含路径上?

【讨论】:

    【解决方案2】:

    std::string 标头是否仅在 Visual Studio 中?

    不完全是,它还依赖于在 Microsoft 的 Visual C++ 运行时中实现的标准 C++ 库的一部分。使用 MSVC 构建二进制文件需要链接 VC++ 运行时。只有静态库可以在不链接到运行时的情况下构建,然后您必须小心不要包含任何需要运行时的标头。

    std::string 标头是否仅在 Visual Studio 中?

    (我最初是这样看标题的。)

    std::stringC++ standard 的一部分。 要在任何支持标准 C++ 的平台上使用std::string,您应该使用#include &lt;string&gt;。它是几乎所有 C++ 编译器都可用的标准头文件。

    不过,每个编译器或平台都可能以自己的方式实现该标准。例如,使用 MSVC,您可以看到 xstring 是 Microsoft 实现 std::string幕后的方式。如果您直接包含xstring.h,您正在编写的代码取决于提供该标头的MSVC 版本。该代码不能移植到其他编译器。

    如果我是对的,微软如何保证下一个 Visual Studio 版本不会改变 xstring 和 std::string 内部结构?

    Microsoft 确实保证下一个 Visual Studio 版本将具有相同的 std::string 内部结构。过去,标准库的实现随着每个 VC++ 运行时版本而改变,这就是为什么 Windows 用户最终在他们的添加/删除程序列表中安装了数十个 VC++ 运行时版本的原因。

    值得庆幸的是,Microsoft 向我们保证 Visual Studio 2015、2017 和 2019 都使用二进制兼容的 C++ 运行时。这意味着使用 Visual Studio 2015 中提供的标准库构建的二进制文件也与使用 2017 和 2019 构建的二进制文件兼容。 (目前)不能保证未来版本的 Visual Studio 不会再次更改 VC++ 运行时实现。

    【讨论】:

    • “如果你直接包含 xstring.h,你就是在明确声明你的代码依赖于提供该头文件的 MSVC 版本!” 忽略了这一点,即@ 987654329@ 也可以这样做
    • @LightnessRacesinOrbit,C++ 标准保证 &lt;string&gt; 存在,但该标头的内容在 MSVC、GCC 和其他编译器之间是不同的。如果您有包含 #include &lt;xstring.h&gt; 的代码,它将在 MSVC 上编译。
    • 再一次,没有人建议应该这样做,也没有人说他们应该这样做。关键是,作为一个包含,即使是为您完成,它的内容也会编译到您的程序中。如果您随后针对一个同样包含该文件的不同版本的对象进行运行时链接,那么您就会遇到问题。这是二进制兼容性概念的基本基础,你现在应该查一下。
    • @LightnessRacesinOrbit,我不确定 您的 点是什么,我的回答是 std::string 作为 C++ 标准的一部分,以回应这个问题的标题! “std::string 标头是否仅在 Visual Studio 中?”。我还回答了有关 Visual Studio 版本之间二进制兼容性的问题。我知道使用不同的编译器会导致这些二进制文件不兼容,我看不出我的回答有什么与此相反的内容。
    • 我直接引用了我所指的文字,并对其中的观点进行了具体的反驳。我不知道如何更清楚,对不起。
    猜你喜欢
    • 2015-10-20
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多