编译错误: 'stoi' 不是 'std' 的成员

23

我的代码:

#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);
                 ^

然而,根据这里的说法,这段代码应该能够正常编译。我将CMakeLists.txt文件中的set(CMAKE_CXX_FLAGS "-std=c++11 -O3")这一行添加到了代码中。

为什么它还是不能编译?


更新:我正在使用gcc,运行gcc --version的输出结果为:

gcc (Ubuntu 5.2.1-22ubuntu2) 5.2.1 20151010

看看这个帖子 http://www.cplusplus.com/forum/beginner/120836/ - jonathanGB
无法在Ubuntu上使用g++ 5.2.1进行复现。 - 2785528
1
首先,gcc是C编译器,而不是C++编译器。g++是C++编译器,因此您应该确保使用正确的编译器进行编译。 - CinchBlue
@DOUGLASO.MOEN 真的吗?这在StackedCrooked上似乎不起作用。 - CinchBlue
@ VermillionAzure:gcc 可以根据文件扩展名编译 C++,但它不会处理链接标准库的问题,而 g++ 包装器则会。 - Nick Matteo
显示剩余5条评论
5个回答

19
在libstdc++中,stoistol等函数的定义以及to_string函数都是在特定条件下受到保护的。
#if ((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \
     && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))

之前我在一个平台上遇到过这种问题(具体来说是Android上的Termux),导致即使使用g++ 6.1和C++14标准,to_string也无法使用。那时候,我只需要:

#define _GLIBCXX_USE_C99 1

在包含任何内容之前,加上这行代码,然后你就会发现这些函数突然存在了。(你应该将它放在第一行,甚至在命令行中使用,而不只是在包含<string>之前,因为另一个头文件可能会先包含<string>,那么它的包含保护将防止它看到你的宏。)

我没有调查为什么这个宏没有被设置。显然,如果你想让你的代码实际工作,这是一个令人担忧的原因(在我的情况下,我并不是特别关心,但 FWIW 没有问题。)

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


libstdc++ 嗯,这个问题肯定与 gcc 相关。他必须使用 g++。因为 Rup(一个 Stack Overflow 用户)说 gcc 会根据文件扩展名选择正确的后端编译器(即将 .c 编译为 C,将 .cc 编译为 C++),并且默认情况下只链接标准的 C 和 GCC 辅助库,而不考虑输入语言;g++ 也会根据扩展名选择正确的后端,只是我认为它将所有的 C 源代码都编译为 C++(即它将 .c 和 .cc 都编译为 C++),并且无论输入语言如何,它都会在链接步骤中包含 libstdc++。 - Soner from The Ottoman Empire
1
@snr:OP没有得到链接器错误,而是得到了编译器错误,说该函数未声明。这不是由于使用“gcc”命令与“g ++”命令引起的。顺便说一下,将g ++称为GCC是完全正确的。 - Nick Matteo
libstdc++ 怎么样? - Soner from The Ottoman Empire
这不是一种链接吗? - Soner from The Ottoman Empire
@snr:是的,它需要被链接进来。如果没有正确地进行链接,std 中的任何东西都不会起作用;这不会仅仅因为缺少一个特定的函数而表现出来,而这个问题可以通过使用 std::atoi 来“修复”。此外,OP(原帖作者)遇到了一个编译器错误:这与链接无关。这意味着编译器在包含的头文件中没有看到所需的定义,尽管应该有。链接是最后发生的:如果 libstdc++ 的必要部分没有被链接进来,将会导致大量未定义的引用,而不是编译器错误。 - Nick Matteo
不要手动设置这些定义。使用正确的编译器标志。问题在于C++标准(__cplusplus >= 201103L)。您应该确保使用std=c++11进行编译。与其设置_GLIBCXX_USE_C99(将C标准版本设置为引入这些符号),您应该使用正确的C++版本。OP提到他们已经设置了set(CMAKE_CXX_FLAGS "-std=c++11 -O3"),这意味着唯一可能的问题是这些标志实际上没有进入编译器命令,或者std稍后在命令行上被重置为其他值。 - Taywee

9

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

 $ 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并观察执行的命令以确保。


不,这确实是平台相关的(我的平台是MIPS的OpenWRT)。 Kundor提出了关于_GLIBCXX_USE_C99的重要观点。 - ogurets

3

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

@我已经解决了这个问题。std::stoi使用libstdc++。它与The GNU Standard C++ Library有关。在gcc中,您必须添加-lstdc++来进行链接。然而,在g++中,libstdc++会自动链接。 使用gcc使用g++

请注意编译方式

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

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

我认为您应该设置像set(CMAKE_EXE_LINKER_FLAGS“-libgcc -lstdc++”)这样的标志(未经测试)。

#include <cstdlib>

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

1
@Karnivaurus 这个问题与C++标准库的链接有关。使用gcc命令时,您必须手动执行类似于-lstdc++的操作,但是g++会自动为您链接。示例 - CinchBlue
@ Vermilion:如果使用atoi正常工作,那么这不是一个链接错误。正如错误信息所说,问题在于函数没有在头文件中声明,因为它们被预处理器移除了。这与链接或gccg++命令无关。 - Nick Matteo
我非常喜欢看到别人的不完整或不正确的信息。仔细查看时,特别关注以下链接:使用gcc使用g++ @Kundor - Soner from The Ottoman Empire
这是错误的答案,即使使用 atoi 解决了 OP 的问题。 - SergeyA
如果问题与链接无关,请解释您的投票否决及其原因。@SergeyA - Soner from The Ottoman Empire
显示剩余6条评论

0
如果您正在使用Cmake进行编译,请在find_package命令之后添加以下行:"add_definitions(-std=c++11)"

0

使用 'set(CMAKE_CXX_STANDARD 11)' 来设置 Cmake


请添加更多细节以扩展您的回答,例如工作代码或文档引用。 - Hamza Anis
在CMakeLists.txt文件中添加一行'set(CMAKE_CXX_STANDARD 11)'。 - xp chen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接