Использование пространства имен std


110

Кажется, существуют разные взгляды на использование слова using в отношении пространства имен std.

Некоторые говорят использовать ' using namespace std', другие говорят, что нет, а вместо этого используют префикс std-функций, которые должны использоваться с ' std::', в то время как другие говорят, что используйте что-то вроде этого:

using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::vector;

для всех std-функций, которые будут использоваться.

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




Ответы:


131

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

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

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

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

#include <algorithm>
using namespace std;

int count = 0;

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

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

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

#include <algorithm>
using namespace std;

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

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

#include <algorithm>

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

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

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}

21
но без префикса std :: он набирает оооочень проще!
xtofl

69
@xtofl: Нет, это не так. Пять символов не так важны при вводе текста, но эти пять символов могут быть очень важны при чтении. А легкость чтения имеет гораздо большее значение, чем простота набора текста для исходного кода, поскольку код гораздо больше читается, чем пишется.
SBI,

3
Вы можете добавить, что оператор using правильно работает с правилами области действия.
Мартин Йорк,

2
@Martin York: добавлены примеры, иллюстрирующие правила области видимости. @Michael Burr: Это, возможно, не так уж и плохо, что мне действительно не нравится, так это то, где сообщения об ошибках для простых ошибок становится намного сложнее интерпретировать или где они не возникают вообще. Например, если предполагается, что функция входит в область видимости, но не входит, а std :: function входит, вместо того, чтобы получить полезную ошибку «идентификатор не распознан», вы часто получаете более неясный аргумент «невозможно преобразовать» X 'или' невозможно создать функцию из шаблона 'ошибка стиля. Хуже того, если незаметно вызывается неправильная функция. Редко, но бывает.
CB Bailey,

5
Что ж, я удивлен, что никто не обсуждал вариант using std::xxx;. Он не загрязняет пространство имен, написание кода будет короче и, я думаю copy, намного более читаемым, чем std::copy.
legends2k

41

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

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

using namespace std

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

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

using std::swap

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

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


10
+1 за упоминание using std::swap(это единственное, что я когда-либо использовал).
sbi

1
+1 за упоминание, что u n sможет распространяться. Просто обратите внимание, что он также может проникнуть в правильно построенные заголовки: их просто нужно включить после мошеннического заголовка.
quamrana 05

1
Но если вы определяете специализацию swapили move(или hashи lessт. Д.), Вам namespace stdвсе равно следует включить эту специализацию . Например:namespace std {template<> class hash<X> {public: size_t operator()(const X&) const};} class X: {friend size_t std::hash<X>::operator()(const X&)};
AJMansfield

28

Сначала немного терминологии:

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

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

using namespace std;

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

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

Также хорошо иметь в виду, что бывают случаи, когда вы должны использовать объявление using. Обратитесь к статье 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директив, и вам это нравится. Несмотря на неоднократные утверждения об обратном, декларации и директивы, использующие пространства имен, не являются злом и не противоречат цели пространств имен. Скорее, они делают пространства имен пригодными для использования.

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

Объявление using добавляет имя в локальную область видимости. С помощью директивы не делает; он просто делает имена доступными в той области, в которой они были объявлены. Например:

namespaceX {
    int i , j , k ;
}

int k ;
void f1()
{
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

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

void f2()
{
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

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

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

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

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

...

Я надеюсь увидеть радикальное сокращение использования глобальных имен в новых программах, использующих пространства имен, по сравнению с традиционными программами на C и C ++. Правила для пространств имен были специально созданы, чтобы не давать преимуществ «ленивому» пользователю глобальных имен перед тем, кто заботится о том, чтобы не загрязнять глобальную область видимости.

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

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


Что касается вашего последнего замечания: Java и C # также имеют гораздо более аккуратные пространства имен. Если бы все в BCL находилось в системе, «использование системы» вызвало бы такие же проблемы, как «использование пространства имен std».
Джефф Харди,

Но программы Java и C #, которые я вижу, обычно включают все используемые ими пространства имен, а не только «Систему» ​​(или ее эквивалент). Таким образом, вместо одной директивы using, которая вводит все используемые имена, есть 5 или 10, которые делают более или менее то же самое. Кроме того, "using namespace std;" действительно причинить столько проблем?
Майкл Бёрр,

Проблема в том, что std имеет слишком много общих имен, и включение одного стандартного заголовка может включать все остальные. У нас нет хорошего контроля над тем, что импортируется, слишком много рисков. Я не знаю достаточно о Java и C #, но я знаю об Аде, которая имеет гораздо лучшую модульную систему, чем C ++, и где импорт имен обычно не одобряется. В общем, это сначала вопрос соглашения об именах (я видел людей, использующих префикс, а также пространство имен, отсутствие импорта не имеет смысла), а затем стиля.
AProgrammer

1
Я все еще не уверен, что это реальная проблема. Я вижу, что директивы using используются все время без серьезных недостатков. Опять же, у меня нет проблем с тем, чтобы их не использовать. Я просто предпочитаю, чтобы std::квалификаторы не загромождали код - есть другие способы избежать этого (обычно помогают объявления using или typedef).
Майкл Берр,

1
@AProgrammer: вы говорите: «список - это естественный идентификатор для идентификации списка в интерпретаторе Lisp» - но наличие using namespace std;директивы « » не мешает вам объявить свой естественный идентификатор ' list' - просто если вы это сделаете, вы не сможете более длительное использование std::listбез квалификации. Это ничем не отличается от using namespace std;директивы " ". Или я что-то упускаю?
Майкл Берр,

17

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

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

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

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

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

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

Для других пространств имен вы также должны учитывать используемые соглашения об именах. Я знаю проект, который использует пространство имен (для управления версиями) и префикс для имен. Выполнение using namespace Xthen почти без риска, и невыполнение этого приводит к глупо выглядящему коду 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, поэтому библиотеку «движка» можно было использовать без повторной компиляции ее пользователей. Интеграционные тесты прошли нормально. Опубликован новый «модуль». Следующая компиляция движка сломалась, когда его код не был изменен.


1
Один из контролируемых случаев, когда я считаю приемлемым использование пространства имен, - это публикация кода. Упрощение облегчает компоновку страницы и помогает сконцентрироваться на видимой точке. Недостатком является то, что это не совсем хорошая практика, поэтому я бы не стал использовать его в книгах для начинающих.
AProgrammer

1
Я думаю, что ввод std :: - это небольшая плата за ясность
paoloricardo

4
@paoloricardo: С другой стороны, я думаю, что наличие std :: show повсюду - это ненужный визуальный беспорядок.
Майкл Бёрр,

1
@ Майкл: ты платишь деньги и делаешь свой выбор!
paoloricardo

2
Благодарим за то, что нашли время добавить подробности проблемы, с которой вы столкнулись.
Майкл Бёрр,

4

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

using namespace std;

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

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

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


4

Обе

using std::string;

и

using namespace std;

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

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


3

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

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;
}

@AraK: пространство имен dir = boost :: filesystem; Полагаю, это псевдоним?
paoloricardo

@paoloricardo: Да, вот что это такое.
sbi

2
Итераторы следует увеличивать на ++i, а не i++потому, что, если он даже определен, создает ненужную временную копию итератора.
Феликс Домбек

2

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

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

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

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

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


3
Специализация std :: swap была бы полной специализацией - вы не можете частично специализировать шаблоны функций. Любая программа может частично специализировать любой стандартный шаблон библиотеки, если эта специализация зависит от типа, определенного пользователем.
CB Bailey,

@Charles: Да, вы правы, конечно, нет FTPS. И я могу специализировать шаблоны внутри std, но не перегружать. Извините за этот тупик. Пост поправлю.
sbi

2
Я не думаю, что целью using namespaceдирективы было также вводить текст ; скорее, это было сделано для облегчения чтения , потому что, как вы говорите, этот код придется читать десятки, сотни или тысячи раз. А для некоторых людей он читается намного проще и меньше std::беспорядка. Но это, вероятно, сводится к личной способности восприятия; некоторые люди отфильтровывают std::или даже нуждаются в нем в качестве руководства (например, с засечками), другие спотыкаются и чувствуют себя как на ухабистой дороге.
Lumi


1
@sbi: Нет, это не объективно. Это зависит от того, считаете ли вы std :: полезным или беспорядочным. Больше беспорядка -> меньше ясности.
Джошуа Ричардсон

2

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

Вот полная и документированная демонстрация правильного использования пространства имен :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see /programming/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

Вывод:

Our log: 42
Standard log: 1.43508

1

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

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

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

РЕДАКТИРОВАТЬ: как указано в другом ответе, вы никогда не должны помещать a using namespaceв файл заголовка, поскольку он будет распространяться на все файлы, включая этот заголовок, и, таким образом, может вызвать нежелательное поведение.

EDIT2: исправил мой ответ, благодаря комментарию Чарльза.


2
using namespace std;импортирует содержимое stdпространства имен в глобальное пространство имен. Это не меняет пространство имен по умолчанию. Определение чего-либо в глобальном пространстве имен после a using namespace stdне волшебным образом поместит это в stdпространство имен.
CB Bailey,

Извините, я не это имел в виду. Спасибо, что указали на это, я исправлю свой ответ.
Wookai

1
Ребята: спасибо за отзывы. Похоже, что в целом безопаснее не использовать «using namespace std» и избегать потенциальных двусмысленностей. В целом использование 'std :: xxx' привлекает меня больше, чем объявление списка различных функций в начале исходного файла, поскольку оно однозначно определяет намерения человека.
paoloricardo

1
Цитата (кроме случаев, когда пространство имен слишком длинное). Вы можете использовать псевдоним пространства имен, чтобы помочь в этом. 'пространство имен Rv1 = Thor :: XML :: XPath :: Rules :: Light :: Version1;' Обратите внимание на псевдонимы и оба варианта подчиняются правилам области видимости;
Мартин Йорк,

0

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


0

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

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

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

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

Итак, это мой совет:

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


0

Есть несколько способов исправить это.

Первое: используйте то же, что и вы.

Во-вторых: сделать namespace S = std;, уменьшив 2 символа.

Третье: использование static.

Четвертое: не используйте имена, которые stdиспользуют.


-1

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

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


Пространства имен на самом деле не предназначены для замены имен другими, но эквивалентными функциями. Они предназначены для предотвращения непреднамеренного конфликта имен.
Майкл Бёрр,

Да, поэтому единственное оправдание директивы using, которая нарушает это, - это позволить вам переключать функции в новое пространство имен.
Мартин Беккет,

Я думаю, вы бы встретили очень много программистов, которые жаловались бы на то, что это неприятная проблема в пространствах имен, и хотели бы выбросить их из окна, если бы не было директивы using. Насколько мне известно, каждый язык, использующий пространства имен, имеет что-то похожее на директиву using, чтобы убрать их с дороги, когда вы хотите, чтобы они не мешали. Если директивы бесполезны, почему они существуют везде?
Майкл Бёрр,

Я думаю, что «использование» было предназначено для того, чтобы позволить вам переключиться на альтернативные реализации, а не экономить на вводе трех букв. Мне нравится использовать "std :: Foo", потому что он служит для программиста контрактом, что я использую обычный Foo, и им не нужно проверять. Я согласен, что не хотел бы набирать com.microsoft.visual-studio.standard-library.numbers.int foo, некоторые объявления итераторов в STL выглядят так. Python отлично справляется с задачей извлекать из модулей декорированные или недекорированные наборы функций.
Мартин Беккет,

-1

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

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&); 
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.