Какова область действия объявления using в C++?

Я использую объявление using в C++, чтобы добавить std :: string и std :: vector в локальное пространство имен (чтобы не вводить ненужные символы std ::).

using std::string;
using std::vector;

class Foo { /*...*/ };

Каков объем этого объявления? Если я сделаю это в заголовке, будет ли он вставлять эти объявления using в каждый файл cpp, который включает заголовок?

На всякий случай это не ясно из других ответов здесь: - Не помещайте объявление using (или директиву using) в область видимости файла во включаемом файле / заголовке! Это вызовет головную боль для пользователей заголовка.

Michael Burr 21.10.2008 23:07

Фактически, не помещайте объявление using (тем более директива) в заголовок совсем, даже в пространстве имен! См. объем использования объявления в пространстве имен для проблем, которые это вызывает.

Nils von Barth 22.05.2016 18:07

@NilsvonBarth: Это немного упрощено. Использование using в области классов и функций безопасно в отношении обсуждаемой проблемы.

Sebastian Mach 17.10.2018 09:45

Возможно, вам будет интересно прочитать о Поиск ADL C++характерная черта.

Alexis Wilke 05.08.2019 07:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
105
5
49 194
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

В указанном случае - файл («единица перевода»), что означает «да», каждый файл, который ее включает.

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

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

Обратите внимание, что объявление using в классе не ведет себя так же, как вне класса - например, вы не можете использовать его, чтобы ввести cout вместо std::cout в область действия класса.

Zero 05.12.2012 03:07

Это верно. Область видимости - это модуль, который использует объявление using. Если какие-либо файлы заголовков, которые включает модуль, имеют объявления using, областью этих объявлений будет этот модуль, а также любые другие модули, которые включают те же заголовки.

Ответ принят как подходящий

Когда вы #include заголовочный файл в C++, он помещает все содержимое заголовочного файла в то место, которое вы включили в исходный файл. Таким образом, включение файла с объявлением using имеет тот же эффект, что и объявление using в верхней части каждого файла, который включает этот файл заголовка.

... что вообще плохо.

Catskul 16.02.2011 08:25

Но если вы поместите объявление using внутри namespace, оно будет ограничено рамками этого пространства имен, так что в целом это нормально (с обычными оговорками в отношении ваших конкретных потребностей и стиля).

Zero 05.12.2012 03:09

... но если вы помещаете using в пространство имен, убедитесь, что вы не пытаетесь обойти что-то, что обычно является плохой идеей, например, вы не можете заключить методы класса, объявленные вне пространства имен Y, внутри другого пространство имен X, чтобы вы могли локально использовать пространство имен X. Вот почему мы в первую очередь использовали namespace :: resolvers. Если это такая большая проблема с набором текста, либо макрос (который может легко привести к запаху кода), либо, что еще лучше, изолировать его в собственном исходном файле .cpp, где вы будете использовать пространство имен только там.

osirisgothra 17.01.2014 21:29

Хотя этот и подобные ответы являются хорошими советами, они не отвечают на вопрос.

Emile Cormier 23.12.2018 22:20

В файлах заголовков нет ничего особенного, что могло бы не допустить объявления using. Это простая замена текста еще до начала компиляции.

Вы можете ограничить объявление using областью действия:

void myFunction()
{
   using namespace std; // only applies to the function's scope
   vector<int> myVector;
}

Никогда не думал, что смогу использовать его внутри функции!

Agostino 05.03.2015 01:50

У меня есть куча пространств имен, которые все используются одним файлом типа «конгломератор», и модульное тестирование gmock было очень утомительным, потому что каждый тест использовал вещи из определенного пространства имен, и я думал, что должен квалифицировать каждую переменную. Использование using внутри функции (или даже макроса gtest TEST!) Делает мою жизнь намного лучше!

dwanderson 11.12.2015 19:09

Область видимости - это та область, в которой находится объявление using.

Если это глобальная область видимости, то она будет глобальной. Если он находится в глобальной области действия файла заголовка, то он будет в глобальной области видимости каждого исходного файла, который включает заголовок.

Итак, общий совет - избегать использования объявлений в глобальной области заголовочных файлов.

Этого недостаточно. Заменить Избегать на Не

Martin York 22.10.2008 03:27

Но избегать лучше, чем не делать. «Избегайте попадания в другие машины»

bobobobo 08.08.2009 07:00

Объем оператора using зависит от того, где он находится в коде:

  • Размещенный в верхней части файла, он имеет область действия по всему файлу.
  • Если это файл заголовка, он будет иметь область видимости во всех файлах, которые включают этот заголовок. Как правило, это "не хорошая идея", так как он может иметь неожиданные побочные эффекты.
  • В противном случае оператор с использованием имеет область действия в блоке, который содержит его, от точки, в которой он встречается, до конца блока. Если он помещен в метод, он будет иметь область видимости в этом методе. Если он помещен в определение класса, он будет иметь область видимости внутри этого класса.

Я думал, что невозможно добавить оператор using в область действия класса ...? Из-за этого у меня был тот же вопрос, что и у OP, так как я не хотел постоянно набирать std::. У меня есть классы, которые используют много векторов с умными указателями, а пятисимвольный префикс std:: добавляет большую длину строки, что, как мне кажется, читается хуже. Поэтому мне было интересно, в порядке ли директива using в пространстве имен, содержащем класс? (Даже если в заголовке.)

thomthom 15.12.2013 13:37

Что насчет того, если он помещен в сферу namespace { ... }?

einpoklum 20.11.2015 12:09

Таким образом, вы можете полностью написать: {using namespace blabla; class blah {}; } и что использование будет применяться только к классу?

Dinaiz 01.09.2016 12:48

Есть несколько безоговорочных комментариев, когда они говорят «Не делайте этого». Это слишком сурово, но нужно понимать, когда это нормально.

Запись using std::string - это никогда не нормально. Запись using ImplementationDetail::Foo в ваш собственный заголовок, когда этот заголовок объявляет ImplementationDetail :: Foo, может быть в порядке, тем более, если объявление using происходит в вашем пространстве имен. Например.

namespace MyNS {
    namespace ImplementationDetail {
        int Foo;
    }
    using ImplementationDetail::Foo;
}

Затем пользователь заголовка может записать MyNS::Foo

Peter Remmers 28.02.2012 17:03

Лучшим примером является using boost::posix_time::ptime. Конечно, пользователь мог бы написать MyNS::ptime, но это еще не конец света, и это может быть компенсировано удобством наличия таких функций, как MyFunction(ptime a, ptime b).

Zero 05.12.2012 03:04
Почемуusing std::string никогда не годится? Даже в вашем собственном пространстве имен, чтобы сохранить много префиксов std::?
thomthom 15.12.2013 13:39

@thomthom - это нормально, если он заключен в область видимости, такую ​​как ваше собственное пространство имен.

jcoffland 17.11.2016 07:43

Другие вопросы по теме