【问题标题】:Compile error: 'stoi' is not a member of 'std'编译错误:“stoi”不是“std”的成员
【发布时间】:2016-06-26 00:34:10
【问题描述】:

我的代码:

#include <iostream>
#include <string>

int main()
{
    std::string test = "45";
    int myint = std::stoi(test);
    std::cout << myint << '\n';
}

给我编译错误:

error: 'stoi' is not a member of 'std'
     int myint = std::stoi(test);
                 ^

但是,根据here,这段代码应该可以正常编译。我在CMakeLists.txt 文件中使用set(CMAKE_CXX_FLAGS "-std=c++11 -O3") 行。

为什么不编译?


更新:我正在使用 gcc,并运行 gcc --version 打印输出:

gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010

【问题讨论】:

  • 您没有指定您使用的编译器版本。
  • @CaptainObvlious,我使用的是 gcc 版本 5.2.1
  • 在 Fedora 24 上使用 gcc 6.1.1 编译没有问题。
  • @Karnivaurus 首先,gcc 是 C 编译器,而不是 C++ 编译器。 g++ 是 C++ 编译器,因此您应该确保使用正确的编译器进行编译。

标签: c++


【解决方案1】:

在libstdc++中,stoi、stol等的定义,以及to_string函数,都是由条件来保护的

#if ((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
     && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))

我之前在一个平台(即 Android 上的 Termux)上遇到过这种情况,导致 to_string 即使使用 g++ 6.1 和 C++14 标准也不可用。在那种情况下,我只是这样做了

#define _GLIBCXX_USE_C99 1

在添加任何东西之前,瞧,突然间功能就存在了。 (你应该把它放在最前面,甚至放在命令行上,而不是在包含&lt;string&gt;之前,因为另一个标题可能首先包含&lt;string&gt;,然后它的包含守卫会阻止它看到你的宏。)

我没有调查为什么一开始就没有设置这个宏。显然,如果您希望您的代码实际工作,这是一个值得关注的问题(在我的情况下,我没有特别关注,但 FWIW 没有问题。)

您应该检查_GLIBCXX_USE_C99 是否未定义,或者_GLIBCXX_HAVE_BROKEN_VSWPRINTF 是否已定义(可能是MinGW 的情况?)

【讨论】:

  • libstdc++ 嗯,OP 问题肯定与gcc 有关。他必须使用g++。因为 Rup(SO 用户)说 gcc 将根据文件扩展名选择正确的后端编译器(即,将 .c 编译为 C,将 .cc 编译为 C++)并将二进制文件链接到标准 C 和 GCC 帮助程序库默认不考虑输入语言; g++ 还将根据扩展名选择正确的后端,除了我认为它将所有 C 源代码编译为 C++(即它将 .c 和 .cc 都编译为 C++),并且无论输入语言如何,它都在其链接步骤中包含 libstdc++。
  • @snr:OP 没有收到链接器错误,而是收到了编译器错误,表示未声明该函数。这不是由使用gcc 命令与g++ 命令引起的。顺便说一句,将 g++ 称为 GCC 是完全正确的。
  • libstdc++ 呢?
  • 不就是一种链接吗?
  • @snr:是的,它需要被链接进去。如果它没有被正确链接,来自std 的nothing 会起作用;缺少一个特定功能不会反映出这一点,可以通过使用std::atoi 来“修复”它。此外,OP 得到一个编译器错误:这与链接没有任何关系。这意味着编译器没有在包含的头文件中看到所需的定义,即使它应该有。链接最后发生:如果未链接 libstdc++ 的必要部分,则会导致大量未定义的引用,而不是编译器错误。
【解决方案2】:

std::stoi 是C++11 function。您必须使用 -std=c++11 在 g++ 和 clang++ 中启用它。这是实际问题,而不是链接错误或特定的预处理器定义。

 $ cat test.cxx
#include <iostream>
#include <string>

int main()
{
    std::string test = "45";
    int myint = std::stoi(test);
    std::cout << myint << '\n';
}
 $ g++ -otest test.cxx
test.cxx: In Funktion »int main()«:
test.cxx:7:17: Fehler: »stoi« ist kein Element von »std«
     int myint = std::stoi(test);
                 ^
 $ g++ -otest test.cxx -std=c++11
 $ ./test
45
 $

编辑:我刚刚看到你使用了 c++11。你确定这会成为你的编译选项吗?检查生成的makefile,观察执行的命令确定。

【讨论】:

  • 不,这确实是平台相关的(我的平台是 OpenWRT for MIPS)。 Kundor 对 _GLIBCXX_USE_C99 提出了很好的观点。
【解决方案3】:

您的版本似乎是最新的,所以应该没有问题。我想可能和gcc有关。尝试g++。(很可能是自动链接问题。如果您只是在 C++ 文件上运行 gcc,它不会像 g++ 那样“正常工作”。那是因为它不会自动链接到 C++ 标准库等。)。我的第二个建议是尝试std::atoi。

@我已经解决了这个问题。 std::stoi 使用 libstdc++。它是关于 GNU 标准 C++ 库。在gcc 中,您必须链接添加-lstdc++。但是,在 g++ 中,libstdc++ 是自动链接的。 using gcc 和 using g++

注意编译方式

使用 g++:g++ -std=c++11 -O3 -Wall -pedantic main.cpp &amp;&amp; ./a.out

使用 gcc:gcc -std=c++11 -O3 -Wall -pedantic -lstdc++ main.cpp &amp;&amp; ./a.out

我认为你应该设置像 set(CMAKE_EXE_LINKER_FLAGS "-libgcc -lstdc++") 这样的标志(未测试)

#include <cstdlib>

int myInt = std::atoi(test.c_str());

【讨论】:

  • 谢谢 - 使用 std::atoi 为我工作。虽然我仍然不确定std::stoi 的潜在问题...
  • @Karnivaurus 这个问题与 C++ 标准库中的链接有关。使用gcc 命令,您必须手动使用-lstdc++ 之类的命令,但g++ 会自动为您链接。 Example
  • @Vermilion:如果它在 atoi 上运行良好,那么这不是链接错误。正如错误首先所说的那样,函数没有在头文件中声明,因为它们被预处理器删除了。这与链接或gcc vs g++ 命令无关。
  • 我真的很喜欢看到某人的不完整或不正确的信息。仔细阅读并特别注意链接:with gcc 和 with g++@Kundor
  • @snr:是的,这完美地证明了我在上面给出的所有原因,为什么你的解释不正确。正如我所说:使用gcc,nothing 有效:并非只有一个函数stoi 会出现问题,将其更改为atoi 将使其神奇地工作。没有任何效果。而且,这些错误都是 LINKER ERRORS。没有一个编译器错误,因为编译器对链接一无所知。当编译器说没有找到某些东西时,这意味着它不在提供给编译器的文本中。这与未找到引用的链接器不同。
【解决方案4】:

如果你使用Cmake编译,添加一行:

“add_definitions(-std=c++11)”

在 find_package 命令之后。

【讨论】:

    【解决方案5】:

    对Cmake

    使用'set(CMAKE_CXX_STANDARD 11)'

    【讨论】:

    • 请添加更多详细信息以扩展您的答案,例如工作代码或文档引用。
    • 在 CMakeLists.txt 中添加行 'set(CMAKE_CXX_STANDARD 11)'
    猜你喜欢
    • 1970-01-01
    • 2015-09-24
    • 2016-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-12
    • 2012-08-31
    • 1970-01-01
    相关资源
    最近更新 更多