Почему пропуск "#include <string>" только иногда приводит к сбоям компиляции? - PullRequest
24 голосов
/ 03 марта 2012

Я новичок в C ++.Когда я пишу код, иногда я пишу #include <string>, и код работает, в других случаях я не пишу #include <string>, а код не работает.Но иногда это работает без #include <string>.

Так я должен написать #include <string>, чтобы код работал?

Ответы [ 6 ]

20 голосов
/ 03 марта 2012

Если вы используете члены, которые объявлены внутри стандартного заголовка string, тогда да, вы должны включить этот заголовок прямо или косвенно (через другие заголовки).

Некоторые компиляторына некоторых платформах может * компилироваться некоторое время месяца, даже если вы не включили заголовок.Такое поведение неудачно, ненадежно и не означает, что вы не должны включать заголовок.

Причина заключается в том, что вы просто включили другие стандартные заголовки, которые также включают string,Но, как я уже сказал, на это, в общем, нельзя полагаться, и это также может очень внезапно измениться (например, при установке новой версии компилятора).

Всегда включать все необходимые заголовки.К сожалению, не существует надежной онлайн-документации, в которую нужно включать заголовки.Обратитесь к книге или официальному стандарту C ++.

Например, следующий код компилируется с моим компилятором (gcc 4.6):

#include <iostream>

int main() {
    std::string str;
}

Но если я удалю первую строку,он больше не компилируется, хотя заголовок iostream на самом деле не должен быть связан.

2 голосов
/ 03 марта 2012

Хотя в конкретном исходном файле нет прямого вхождения #include <string>, это не означает, что он не был включен в другой заголовочный файл.Рассмотрим это:

Файл: header.h

#if !defined(__HEADER_H__)
#define __HEADER_H__

// more here
#include <string>
// ...and here

#endif

Файл: source1.cc

#include <string>

void foo()
{
    // No error here.
    string s = "Foo";
}

Файл: source2.cc

#include <header.h>

void bar()
{
    // Still no error, since there's a #include <string> in header.h
    string s = "Bar";
}

Файл: source3.cc

void zoid()
{
    // Here's the error; no such thing as "string", since non of the
    // previous headers had been included.
    string s = "Zoid";
}
2 голосов
/ 03 марта 2012

Возможно, что другие заголовки, которые вы делаете , содержат #include <string> в них.

Тем не менее, обычно хорошей идеей является #include <string> непосредственно в вашем коде, даже если это не является строго необходимым для успешной сборки, в случае изменения этих «других» заголовков - например, из-за другой (или другой версии) реализация компилятора / стандартной библиотеки, платформа или даже просто конфигурация сборки.

(Конечно, это обсуждение относится к любому заголовку, а не только к <string>.)

0 голосов
/ 26 апреля 2019

Даже если вы явно не включили строку, она была включена из-за другого стандартного заголовка, который вы включили.Например, вектор может содержать строку.Когда вы включаете вектор, каждая вещь из вектора будет включена в ваш файл.

Я думаю, что будущие версии Cpp должны иметь ключевое слово include_module или module;которые включают только определенный модуль из файла.Таким образом, если файл имеет 3 класса, мы включаем только тот, который нам нужен.

например
-I "../mingw/lib/include"

 module <string>

Поиск в каталоге файлов, которые определяют класс строки.Компиляция будет значительно медленнее.

0 голосов
/ 15 января 2014

Неправда, что строка заголовка включена другими заголовками. Сама строка заголовка имеет только включает в себя. Нет определений. Таким образом, все необходимые определения, необходимые для использования строки, находятся в заголовках, включенных в строку заголовка. Эти заголовки уже могут быть включены другими заголовками. Тогда все работает. Например, заголовок ios содержит stringbuf, который включает ...

0 голосов
/ 03 марта 2012

Если вы просто используете указатель / ссылку на определенный пользователем тип, тип должен быть объявлен только:

class my_class;
void foo(const my_class& c);

Но когда вы используете значение, компилятору нужно знать размер, а вместе с ним и определение типа.

И имейте в виду, что стандартные заголовки могут включать другие заголовки, что не означает автоматически, что все реализации делают это, поэтому вы не можете полагаться на это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...