Используя Пространство имен станд.

Звуки, хорошие мне. Я - как не американский гражданин - тогда получаю доступ к программному обеспечению с открытым исходным кодом что американские налогоплательщики, оплаченные:)

105
задан Ondrej Slinták 2 September 2018 в 13:09
поделиться

13 ответов

Как и в Java, где вы можете использовать либо включить java.util. *, Либо просто выбрать каждый класс индивидуально, это зависит от стиля. Обратите внимание, что вы не хотите, чтобы один использовал пространство имен std в начале вашей файловой / широкой области, потому что вы загрязните пространство имен и, возможно, столкнетесь с конфликтами, побеждая точку пространств имен. Но если у вас есть функция, которая использует много STL, она загромождает код, чтобы в вашей логике был беспорядочный синтаксис префиксов, и вам, вероятно, следует рассмотреть возможность использования либо с использованием пространства имен std (при использовании различных классов ) или индивидуально с использованием (при частом использовании нескольких классов).

0
ответ дан 24 November 2019 в 03:58
поделиться

с использованием пространства имен std импортирует содержимое пространства имен std в текущее. Таким образом, преимущество состоит в том, что вам не придется вводить std :: перед всеми функциями этого пространства имен. Однако может случиться так, что у вас есть разные пространства имен, которые имеют функции с одинаковыми именами. Таким образом, вы можете прекратить не вызывать тот, который вам нужен.

Указание вручную, какие из них вы хотите импортировать в std , предотвратит это, но может привести к появлению длинного списка использования в начале вашего файл, который некоторые разработчики сочтут уродливым;)!

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

РЕДАКТИРОВАТЬ: как указано в другом ответе,

1
ответ дан 24 November 2019 в 03:58
поделиться

Это обсуждение будет продолжаться до тех пор, пока среда IDE, с которой вы работаете, не будет достаточно гибкой, чтобы отображать или скрывать точную информацию, которая вам нужна.

Это потому, что вы хотите, чтобы ваш код внешний вид зависит от поставленной задачи.

При создании исходного кода я предпочитаю видеть, какой именно класс я использую: это std :: string или BuzFlox :: Obs :: string class?

При разработке потока управления меня даже не интересуют типы переменных, но я хочу сосредоточиться на if и , а и продолжают .

Вот мой совет:

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

0
ответ дан 24 November 2019 в 03:58
поделиться

Я предпочитаю использовать :: , когда это возможно.

std::list<int> iList;

Ненавижу писать:

for(std::list<int>::iterator i = iList.begin(); i != iList.end(); i++)
{
    //
}

Надеюсь, с C ++ 0x я бы написал это :

for(auto i = iList.begin(); i != iList.end(); i++)
{
    //
}

Если пространство имен очень длинное,

namespace dir = boost::filesystem;

dir::directory_iterator file("e:/boost");
dir::directory_iterator end;

for( ; file != end; file++)
{
    if(dir::is_directory(*file))
        std::cout << *file << std::endl;
}
3
ответ дан 24 November 2019 в 03:58
поделиться

Если у вас нет риска конфликта имен в вашем коде с std и другими библиотеками, вы можете использовать:

using namespace std;

Но если вы хотите точно знать, насколько ваш код зависит от документации или существует риск конфликта имен. Используйте другой способ:

using std::string;
using std::cout;

Третье решение, не используйте эти решения и пишите std :: перед каждым использованием в коде, это повысит безопасность, но, возможно, немного усложнит код .. .

3
ответ дан 24 November 2019 в 03:58
поделиться

И

using std::string;

, и

using namespace std;

добавляют некоторые символы (один или несколько) в глобальное пространство имен. А добавление символов в глобальное пространство имен - это то, что вы никогда никогда не должны делать в файлах заголовков. Вы не можете контролировать, кто будет включать ваш заголовок, есть много заголовков, которые включают другие заголовки (и заголовки, которые включают заголовки, которые включают заголовки, и так далее ...).

В файлах реализации (.cpp) это зависит от вас (не забудьте сделать это после всех директив #include). Вы можете взломать только код в этом конкретном файле, чтобы было легче управлять и выяснить причину конфликта имен. Если вы предпочитаете использовать std :: (или любой другой префикс, в вашем проекте может быть много пространств имен) перед идентификаторами, все в порядке. Если вы хотите добавить идентификаторы, которые вы используете, в глобальное пространство имен, ничего страшного. Если вы хотите взять с собой все пространство имен :-), решать вам. Хотя эффекты ограничены одной единицей компиляции, это приемлемо.

4
ответ дан 24 November 2019 в 03:58
поделиться

Исключение основных (необходимость добавления std :: infront всех объектов / функций stl и меньшая вероятность конфликта, если у вас нет 'using namespace std')

Также стоит отметить, что вы никогда не должны помещать

using namespace std

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

В некоторых случаях очень полезно использовать такие вещи, как

using std::swap

. Как будто существует специализированная версия подкачки, компилятор будет использовать ее, иначе он вернется к std :: swap

. Если вы вызовете std :: swap, вы всегда используйте базовую версию, которая не будет вызывать оптимизированную версию (если она существует).

40
ответ дан 24 November 2019 в 03:58
поделиться

Вы никогда не должны использовать пространство имен std в области пространства имен в заголовке. Кроме того, я полагаю, что большинство программистов удивится, когда они увидят вектор или строку без std :: , поэтому я не думаю, что с использованием пространства имен std лучше. Поэтому я призываю никогда не использовать пространство имен std вообще.

Если вы чувствуете, что должны, добавьте локальные объявления using, например , используя std :: vector . Но спросите себя: чего это стоит? Строка кода пишется один раз (может быть, дважды), но читается десять, сотни или тысячи раз. Сэкономленные усилия при вводе объявления или директивы using незначительны по сравнению с усилиями чтения кода.

Имея это в виду, в проекте десять лет назад мы решили явно квалифицировать все идентификаторы их полными именами пространств имен. То, что сначала казалось неудобным, через две недели превратилось в рутину. Теперь во всех проектах этой компании никто больше не использует директивы или декларации using. (За одним исключением, см. Ниже.) Глядя на код (несколько MLoC) через десять лет, я чувствую, что мы приняли правильное решение.

Я обнаружил, что обычно те, кто выступает против запрета с помощью , обычно не пробовали использовать его для одного проекта. Те, кто пробовал, часто находят это лучше, чем использование директив / деклараций через очень короткое время.

Примечание. Единственное исключение - с использованием std :: swap , который необходим (особенно в универсальном коде) для сбора перегрузок swap () , которые не могут быть помещены в пространство имен std (потому что нам не разрешено помещать поместите в это пространство имен перегрузку std функций).

2
ответ дан 24 November 2019 в 03:58
поделиться

Никогда не используйте using namespace в глобальной области видимости в файле заголовка. Это может привести к конфликту, и лицо, ответственное за файл, в котором возникает конфликт, не может повлиять на его причину.

В файле реализации варианты выбора гораздо менее удачны.

  • Ввод using namespace std приносит все символы из этих пространств имен. Это может быть неприятно, так как почти никто не знает все символы, которые есть (поэтому на практике невозможно применить политику отсутствия конфликтов), не говоря уже о символах, которые будут добавлены. А стандарт C ++ позволяет добавлять в заголовок символы из других заголовков (в стандарте C это не допускается). Это все еще может хорошо работать на практике для упрощения записи в контролируемых случаях. И если возникает ошибка, она обнаруживается в файле, в котором возникла проблема.

  • Ввод с использованием std :: name; имеет преимущество простоты написания без риска импорта неизвестных символов. Цена состоит в том, что вам придется явно импортировать все требуемые символы.

  • Явное определение добавляет немного беспорядка, но я думаю, что это меньше проблем на практике.

В моем проекте я использую явную квалификацию для всех имен, я принимаю использование std :: name, я борюсь против использования пространства имен std (у нас есть интерпретатор lisp, который имеет свой собственный тип списка, и поэтому конфликт неизбежен).

Для других пространств имен вы также должны принять во внимание используемые соглашения об именах. Я знаю проект, который использует пространство имен (для управления версиями) и префикс для имен. Выполнение с использованием пространства имен X тогда почти без риска, и невыполнение этого приводит к глупо выглядящему коду PrefixNS :: pfxMyFunction (...) .

В некоторых случаях вы хотите импортировать символы. std :: swap - самый распространенный случай: вы импортируете std :: swap, а затем используете безусловный swap. Поиск, зависящий от аргумента, найдет соответствующий своп в пространстве имен типа, если он есть, и вернется к стандартному шаблону, если его нет.


Редактировать:

В комментариях Майкл Берр задается вопросом, возникают ли конфликты в реальный мир. Вот настоящий живой пример. У нас есть язык расширения с шепелявым диалектом. У нашего интерпретатора есть включаемый файл lisp.h, содержащий

typedef struct list {} list;

. Нам пришлось интегрировать и адаптировать некоторый код (который я назову "движок"), который выглядел так:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Итак, мы изменили его следующим образом:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

Хорошо . Все работает. Несколько месяцев спустя "module.h" был изменен и теперь включает "list.h". Испытания прошли. «модуль» не был изменен таким образом, чтобы это повлияло на его ABI, поэтому библиотеку «движка» можно было использовать без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.

h, содержащий

typedef struct list {} list;

. Нам пришлось интегрировать и адаптировать некоторый код (который я назову "движком"), который выглядел так:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Итак, мы изменили так:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

Хорошо. Все работает. Несколько месяцев спустя "module.h" был изменен и теперь включает "list.h". Испытания прошли. «модуль» не был изменен таким образом, чтобы это повлияло на его ABI, поэтому библиотеку «движка» можно было использовать без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.

h, содержащий

typedef struct list {} list;

. Нам пришлось интегрировать и адаптировать некоторый код (который я назову "движком"), который выглядел так:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Итак, мы изменили так:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

Хорошо. Все работает. Несколько месяцев спустя "module.h" был изменен и теперь включает "list.h". Испытания прошли. «модуль» не был изменен таким образом, чтобы это повлияло на его ABI, поэтому библиотеку «движка» можно было использовать без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.

t быть модифицированным таким образом, чтобы это повлияло на его ABI, так что "движковая" библиотека может использоваться без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.

t быть модифицированным таким образом, чтобы это повлияло на его ABI, так что "движковая" библиотека может использоваться без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.

17
ответ дан 24 November 2019 в 03:58
поделиться

Большинство пользователей C ++ вполне довольны чтением std :: string , std :: vector и т. Д. Фактически, они видят необработанный vector заставляет меня задуматься, является ли это std :: vector или другим определяемым пользователем вектором .

Я всегда против использования с использованием пространства имен std; . Он импортирует всевозможные имена в глобальное пространство имен и может вызывать всевозможные неочевидные двусмысленности.

Вот некоторые общие идентификаторы, которые находятся в пространстве имен std : count, sort, find, equal, обеспечить регресс. Наличие локальной переменной с именем count означает, что с использованием пространства имен std не позволит вам использовать count вместо std :: count .

Классический пример конфликта нежелательных имен выглядит примерно так. Представьте, что вы новичок и не знаете о std :: count . Представьте, что вы либо используете что-то еще в , либо это связано с, казалось бы, несвязанным заголовком.

#include <algorithm>
using namespace std;

int count = 0;

int increment()
{
    return ++count; // error, identifier count is ambiguous
}

Обычно ошибка длинная и неприятная, потому что std :: count - это шаблон с некоторыми длинными вложенными типами.

Это нормально, потому что std :: count входит в глобальное пространство имен, а функция count скрывает его.

#include <algorithm>
using namespace std;

int increment()
{
    static int count = 0;
    return ++count;
}

Возможно, немного удивительно, но это нормально. . Идентификаторы, импортированные в декларативную область видимости, появляются в общем пространстве имен, которое включает как место их определения, так и место их импорта. Другими словами, std :: count отображается как count в глобальном пространстве имен, но только внутри приращения .

#include <algorithm>

int increment()
{
    using namespace std;
    static int count = 0;
    return ++count;
}

И по тем же причинам count здесь неоднозначен. с использованием пространства имен std не вызывает std :: count , скрывает внешний счетчик , как можно было бы ожидать. Правило using namespace означает, что std :: count выглядит (в функции increment ) так, как если бы он был объявлен в глобальной области видимости, то есть в той же области as int count = 0; и, следовательно, вызывает двусмысленность.

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}
127
ответ дан 24 November 2019 в 03:58
поделиться

Во-первых, немного терминологии:

  • объявление-использования : с использованием std :: vector;
  • директива-использование : с использованием пространства имен std ;

Я думаю, что использование директив using нормально, если они не используются в глобальной области видимости в файле заголовка. Так что наличие

using namespace std;

в вашем .cpp файле на самом деле не проблема, а если окажется, то это полностью под вашим контролем (и при желании его можно даже ограничить определенными блоками). Я не вижу особых причин загромождать код множеством квалификаторов std :: - это просто становится кучей визуального шума. Однако, если вы не используете в своем коде целую кучу имен из пространства имен std , я также не вижу проблем с исключением этой директивы. Это тавтология - если директива не нужна, тогда нет необходимости его использовать.

Точно так же, если вы можете обойтись несколькими объявлениями использования (вместо директив использования ) для определенных типов в пространстве имен std , тогда нет причин, по которым в текущее пространство имен не следует вводить только эти конкретные имена. К тому же, я думаю, что было бы безумием и хлопотно иметь дело с 25 или 30 объявлениями-использованием, когда одна-единственная-директива-использование с таким же успехом могла бы помочь.

Также хорошо иметь в виду, что существуют раз, когда вы должны использовать объявление-использования. Обратитесь к статье 25 Скотта Мейерса: подумайте о поддержке безбрасывающего свопа из Эффективного C ++, Третье издание. Чтобы иметь универсальную шаблонную функцию, используйте «лучший» метод подкачки для параметризованного типа, вам нужно использовать поиск, зависящий от объявления и аргумента (он же ADL или поиск по Кенигу):

template< typename T >
void foo( T& x, T& y)
{
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

Я думаю, нам следует рассмотреть общие идиомы для различных языков, которые в значительной степени используют пространства имен. Например, Java и C # в значительной степени используют пространства имен (возможно, больше, чем C ++). Наиболее распространенный способ использования имен в пространствах имен на этих языках - их массовое внесение в текущую область действия с эквивалентом директивы using. Это не вызывает широко распространенных проблем, и в некоторых случаях проблема решается на основе «исключений», обрабатывая соответствующие имена с помощью полностью определенных имен или псевдонимов - точно так же, как это может быть сделано в C ++.

Херб Саттер и Андрей Александреску говорят об этом в «Правиле 59: не записывайте использование пространств имен в заголовочный файл или перед #include». их книги «Стандарты кодирования C ++: 101 правила, рекомендации и передовые методы»:

Вкратце: вы можете и должны свободно использовать пространство имен, используя декларации и директивы в своих файлах реализации после директив #include и почувствуйте хорошо об этом. Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования.

Stroupstrup часто цитирует слова «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно говорит, что (C.14 [15]), но ссылается на главу C.10.1, где он говорит:

A using-декларация добавляет имя к Вы можете и должны свободно использовать пространство имен, используя объявления и директивы в своих файлах реализации после директив #include , и вам это нравится. Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования.

Stroupstrup часто цитирует слова «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно говорит, что (C.14 [15]), но ссылается на главу C.10.1, где он говорит:

A using-декларация добавляет имя к Вы можете и должны свободно использовать пространство имен, используя объявления и директивы в своих файлах реализации после директив #include , и вам это нравится. Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования.

Stroupstrup часто цитирует слова «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно говорит, что (C.14 [15]), но ссылается на главу C.10.1, где он говорит:

A объявление-использования добавляет имя к Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования.

Stroupstrup часто цитирует слова «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно говорит, что (C.14 [15]), но ссылается на главу C.10.1, где он говорит:

A using-декларация добавляет имя к Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, именно они делают пространства имен пригодными для использования.

Stroupstrup часто цитирует слова «Не загрязняйте глобальное пространство имен» в «Языке программирования C ++, третье издание». Он действительно говорит, что (C.14 [15]), но ссылается на главу C.10.1, где он говорит:

A using-декларация добавляет имя к локальный охват. Директива использования делает не; он просто отображает имена доступны в том объеме, в котором они были объявлены. Например:

 namespaceX {
 int i, j, k;
}

int k;
пусто f1 ()
{
 int я = 0;

using namespaceX; // делаем имена из X доступными

i ++; // местный я
j ++; // X :: j
k ++; // ошибка: X :: k или глобальный k?

:: k ++; // глобальный k

X :: k ++; // X's k
}

пусто f2 ()
{
 int я = 0;

используя X :: i; // ошибка: я дважды объявлен в f2 ()
 используя X :: j;
используя X :: k; // скрывает глобальный k

 i ++;
j ++; // X :: j
k ++; // X :: k
}

Локально объявленное имя (объявленное либо обычным заявлением, либо с помощью объявления-использования) скрывает нелокальный одноименные декларации и любые незаконные перегрузки имени обнаружен в момент объявления.

Обратите внимание на ошибку неоднозначности для k ++ в f1 () . Глобальные имена не указаны предпочтение по именам из пространств имен сделали доступным в глобальном масштабе. Это обеспечивает значительную защиту от случайного совпадения имен, и - главное - гарантирует, что есть нет никаких преимуществ загрязнение глобального пространства имен.

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

...

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

И откуда у "ленивого пользователя глобальных имен" такое же преимущество? Используя преимущества директивы using, которая безопасно делает имена в пространстве имен доступными для текущей области.

Обратите внимание, что есть различие - имена в пространстве имен std стали доступными в область с правильным использованием директивы using (помещая директиву после #includes ) не загрязняет глобальное пространство имен. Это просто делает эти имена доступными и с постоянной защитой от столкновений.

27
ответ дан 24 November 2019 в 03:58
поделиться

Каковы плюсы и минусы каждого

Единственная причина отказаться от std :: состоит в том, что теоретически вы могли бы заново реализовать все функции STL самостоятельно. Тогда ваши функции можно будет переключить с использования std :: vector на my :: vector без изменения кода.

-1
ответ дан 24 November 2019 в 03:58
поделиться

Почему бы, например, не

typedef std::vector<int> ints_t;
ints_t ints1;
....
ints_t ints2;

вместо громоздкого

std::vector<int> ints1;
...
std::vector<int> ints2;

Я считаю, что это намного удобнее для чтения, и это мой стандарт кодирования.

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

void getHistorgram(std::vector<unsigned int>&, std::vector<unsigned int>&);

, которые возвращают значение?

А как насчет

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
-1
ответ дан 24 November 2019 в 03:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: