#c #file-io #fstream
#c #строка #включить
Вопрос:
Я новичок в C . Когда я пишу код, иногда я пишу, #include <string>
и код работает, в других случаях я не пишу, #include <string>
и код не работает. Но иногда это работает без #include <string>
.
Так должен ли я писать #include <string>
так, чтобы код работал?
Комментарии:
1. Люди, какого черта?! Конечно, это реальный, законный вопрос! Откуда берутся все отрицательные и закрывающие голоса? Возвращайтесь в постель.
2. Каким-то образом, на мой взгляд, этот вопрос был таким же эффективным, как
these are not the droids you are looking for
.3. Вопрос мог бы быть сформулирован лучше, но когда они начинают с «Я новичок в C «, можно с уверенностью предположить, что они могут не совсем понимать, как работают includes, и оставить комментарий вместо голосования «закрыть» или «против».
Ответ №1:
Если вы используете элементы, которые объявлены внутри стандартного заголовка string
, тогда да, вы должны включить этот заголовок прямо или косвенно (через другие заголовки).
Некоторые компиляторы на некоторых платформах могут в определенное время месяца компилироваться, даже если вы не включили заголовок. Такое поведение прискорбно, ненадежно и не означает, что вы не должны включать заголовок.
Причина просто в том, что вы включили другие стандартные заголовки, которые также включают string
. Но, как я уже сказал, на это вообще нельзя полагаться, и это также может измениться очень внезапно (например, при установке новой версии компилятора).
Всегда включайте все необходимые заголовки. К сожалению, похоже, что нет надежной онлайн-документации, в которую необходимо включить заголовки. Обратитесь к книге или официальному стандарту C .
Например, следующий код компилируется с моим компилятором ( gcc
4.6):
#include <iostream>
int main() {
std::string str;
}
Но если я удаляю первую строку, она больше не компилируется, хотя iostream
заголовок на самом деле должен быть несвязанным.
Комментарии:
1. Есть идеи, происходит ли это с файлами заголовков, отличными от
<string>
?2. @C.R. Очевидно, что это определенно так, поскольку стандартные заголовки иногда используют друг друга. Например,
std::pair
определено в<utility>
, но нет реализации стандартной библиотеки, которая требует, чтобы вы включили этот заголовок, если вы уже включили<map>
поскольку последнее требуетstd::pair
. То же самое верно и для других типов. Это, кстати, одна из больших слабостей системы заголовков C по сравнению с надлежащей модульной системой.3. Что касается К сожалению, похоже, что нет надежной онлайн-документации, в которую необходимо включить заголовки. вы всегда можете выполнить поиск того, что вы используете на cppreference.com и он сообщит вам, в каком заголовке он находится.
4. @NathanOliver Да, теперь они тщательно документируют это. Предыдущие версии этого не делали. cppreference.com в настоящее время это моя ссылка № 1 для перехода.
Ответ №2:
Возможно, что в них есть другие заголовки, которые вы включаете, которые вы #include <string>
включаете.
Тем не менее, обычно это хорошая идея #include <string>
непосредственно в вашем коде, даже если это не является строго необходимым для успешной сборки, на случай, если эти «другие» заголовки изменяются — например, из-за другой (или иной версии) реализации компилятора / стандартной библиотеки, платформы или даже просто конфигурации сборки.
(Конечно, это обсуждение применимо к любому заголовку, а не только <string>
.)
Ответ №3:
Хотя прямого появления #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";
}
Ответ №4:
Если вы просто используете указатель / ссылку на пользовательский тип, тип должен быть только объявлен:
class my_class;
void foo(const my_classamp; c);
Но когда вы используете значение, компилятору необходимо знать размер, а вместе с ним и определение типа.
И имейте в виду, что стандартные заголовки могут включать другие, что автоматически не означает, что все реализации делают это, поэтому вы не можете на это полагаться.
Ответ №5:
Неверно, что строка заголовка включена в другие заголовки. Сама строка заголовка содержит только includes. Нет определений. Таким образом, все необходимые определения, необходимые для использования string, содержатся в заголовках, включенных в строку заголовка. Эти заголовки могут быть уже включены другими заголовками. Тогда все работает. Заголовок ios, например, включает stringbuf , который включает …
Ответ №6:
Даже если вы явно не включили строку, она была включена из-за другого стандартного заголовка, который вы включили. Например, vector мог содержать строку. Когда вы включаете vector, каждая вещь из vector будет включена в ваш файл.
Я думаю, что в будущих версиях Cpp должно быть ключевое слово include_module или module; которые включают только определенный модуль из файла. Итак, если файл имеет 3 класса, мы включаем только тот, который нам нужен.
например
-I «../mingw/lib/include»
module <string>
Выполняет поиск в каталоге файлов, определяющих класс string. Компиляция была бы значительно медленнее.
Ответ №7:
Как сказал Бранко:
Возможно, что другие заголовки, которые вы включаете, содержат #include в них.
Давайте взглянем на iostream
включает:
#include <bits/c config.h>
#include <ostream>
#include <istream>
если вы проверите, istream
вы можете увидеть некоторые include
итак, вот так мы имеем:
iostream => istream => ios => iosfwd
и в iosfwd
у нас есть библиотека строк! но это не стандартно, это для прямого объявления. в iosfwd
мы имеем:
#включить <bits/stringfwd.h> // Для объявлений пересылки строк.
и в stringfwd.h
:
@file bits/stringfwd.h This is an internal header file, included by other library headers. Do not attempt to use it directly. @headername{string}
итак, вы можете использовать string
без #include <string>
.