Безымянное / анонимное пространство имен против статических функций

Марк Байерс прав в том, что причиной проблемы является катастрофическое обратное отслеживание , однако это последняя проблема, вызывающая проблему, а не бит, который соответствует букве диска.

] Например, в

(?
  ([a-zA-Z0-9_]+
    (
      ([a-zA-Z0-9_\s_\-\.]*[a-zA-Z0-9_]+)
    |
      ([a-zA-Z0-9_]+)
    )\.
    (?[a-zA-Z0-9]{1,6})
  $)
)

вы можете видеть, что

([a-zA-Z0-9_\s_\-\.]*[a-zA-Z0-9_]+)
|
([a-zA-Z0-9_]+)

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

Когда случается, что часть расширения регулярного выражения не подходит, механизм regex отступает и пытается выполнить другую перестановку для части имени файла, надеясь, что это позволит части расширения совпадать - что, конечно, это никогда не будет, но механизм регулярных выражений не может понять это. RegexBuddy , когда вас попросят проверить регулярное выражение на указанном вами пути, прервет попытку матча после 1.000.000 итераций. Регулятор C # будет работать до тех пор, пока он не исчерпает все перестановки, закрепив ваш процессор на 100% за это время.

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

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

474
задан Raedwald 6 December 2017 в 18:57
поделиться

8 ответов

Стандарт C ++ читает в разделе 7.3.1.1 Безымянные пространства имен, абзац 2:

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

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

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

Решение об отказе от использования этого ключевого слова static (повлиять на видимость объявления переменной в единице перевода) было отменено ( ref ). В этом случае использование статического или безымянного пространства имен вернулось к тому, чтобы быть по сути двумя способами сделать одно и то же. Для получения дополнительной информации см. этот SO вопрос.

Неназванные пространства имен по-прежнему имеют то преимущество, что позволяют определять типы локальных единиц перевода. Пожалуйста, смотрите этот ТАК вопрос для более подробной информации.

Автор благодарности Майк Перси за то, что обратил на это мое внимание.

311
ответ дан Community 6 December 2017 в 18:57
поделиться

Существует один пограничный случай, где статичный имеет удивительный эффект (по крайней мере, это было мне). C++ 03 Стандарта указывает в 14.6.4.2/1:

Для вызова функции, который зависит от шаблонного параметра, если имя функции неполный идентификатор , но не шаблонный идентификатор , функции кандидата найдены с помощью обычных правил поиска (3.4.1, 3.4.2) за исключением того, что:

  • Для части поиска с помощью дисквалифицированного поиска имени (3.4.1), только объявления функции с внешней связью от шаблонного контекста определения найдены.
  • Для части поиска с помощью связанных пространств имен (3.4.2), только объявления функции с внешней связью, найденной или в шаблонном контексте определения или в шаблонном контексте инстанцирования, найдены.

...

ниже кода будет звонить foo(void*) а не foo(S const &), как Вы могли бы ожидать.

template <typename T>
int b1 (T const & t)
{
  foo(t);
}

namespace NS
{
  namespace
  {
    struct S
    {
    public:
      operator void * () const;
    };

    void foo (void*);
    static void foo (S const &);   // Not considered 14.6.4.2(b1)
  }

}

void b2()
{
  NS::S s;
  b1 (s);
}

Сам по себе это является, вероятно, не настолько большим соглашение, но оно действительно выделяет это для полностью совместимого компилятора C++ (т.е. один с поддержкой export) static, ключевое слово будет все еще иметь функциональность, которая не доступна никаким другим способом.

// bar.h
export template <typename T>
int b1 (T const & t);

// bar.cc
#include "bar.h"
template <typename T>
int b1 (T const & t)
{
  foo(t);
}

// foo.cc
#include "bar.h"
namespace NS
{
  namespace
  {
    struct S
    {
    };

    void foo (S const & s);  // Will be found by different TU 'bar.cc'
  }
}

void b2()
{
  NS::S s;
  b1 (s);
}

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

Обновление для современного C++

С C++ '11, у членов пространства имен без имени есть внутренняя связь неявно (3.5/4):

пространство имен без имени или пространство имен, объявленное прямо или косвенно в пространстве имен без имени, имеют внутреннюю связь.

, Но в то же время 14.6.4.2/1 был обновлен для удаления упоминания о связи (взятый от C++ '14):

Для вызова функции, где постфиксное выражение является зависимым именем, функции кандидата найдены с помощью обычных правил поиска (3.4.1, 3.4.2) за исключением того, что:

  • Для части поиска с помощью дисквалифицированного поиска имени (3.4.1), только объявления функции от шаблонного контекста определения найдены.

  • Для части поиска с помощью связанных пространств имен (3.4.2), только объявления функции, найденные или в шаблонном контексте определения или в шаблонном контексте инстанцирования, найдены.

результат состоит в том, что это конкретное различие между статическими и участниками пространства имен без имени больше не существует.

33
ответ дан Moshe Slavin 6 December 2017 в 18:57
поделиться

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

7
ответ дан Firas Assaad 6 December 2017 в 18:57
поделиться

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

  • Анонимные пространства имен могут быть вложены друг в друге, обеспечив несколько уровней защиты, из которых символы не могут выйти.
  • Несколько анонимных пространств имен могли быть помещены в тот же исходный файл, создав в действительности различные объемы статического уровня в том же файле.

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

2
ответ дан Commodore Jaeger 6 December 2017 в 18:57
поделиться

Отличие компилятора между анонимными пространствами имен и статическими функциями можно увидеть при компиляции следующего кода.

#include <iostream>

namespace
{
    void unreferenced()
    {
        std::cout << "Unreferenced";
    }

    void referenced()
    {
        std::cout << "Referenced";
    }
}

static void static_unreferenced()
{
    std::cout << "Unreferenced";
}

static void static_referenced()
{
    std::cout << "Referenced";
}

int main()
{
    referenced();
    static_referenced();
    return 0;
}

Компиляция этого кода с VS 2017 (с указанием флага предупреждения уровня 4 / W4 для включения предупреждения C4505: удаленная локальная функция была удалена ) и gcc 4.9 с помощью -Wunused-function или - Флаг на стене показывает, что VS 2017 выдаст предупреждение только для неиспользуемой статической функции. gcc 4.9 и выше, а также clang 3.3 и выше, будут генерировать предупреждения для функции без ссылок в пространстве имен, а также предупреждение о неиспользуемой статической функции.

Живая демоверсия gcc 4.9 и MSVC 2017

2
ответ дан masrtis 6 December 2017 в 18:57
поделиться

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

, Но более старый компилятор, работающий на Солярисе, на котором мы связаны узами брака до неуказанного будущего выпуска, будет иногда принимать его, и другие времена отмечают его как ошибку. Ошибка не то, что волнует меня, это - то, что это могло бы сделать, когда это принимает это. Таким образом, пока мы не идем современные через плату, мы все еще используем статичный (обычно ограниченный по объему классом) функции, где мы предпочли бы анонимное пространство имен.

6
ответ дан Don Wakefield 6 December 2017 в 18:57
поделиться

Помещение методов в анонимном пространстве имен предотвращает Вас от случайного нарушения Одно Правило Определения, позволяя Вам никогда не взволновать по поводу именования Ваших вспомогательных методов то же как некоторый другой метод, в котором можно связаться.

И, как указано luke, анонимные пространства имен предпочтены стандартом по статическим участникам.

66
ответ дан hazzen 6 December 2017 в 18:57
поделиться

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

, Например, в моем файле XmlUtil.cpp, я определяю пространство имен XmlUtil_I {...} Для всех моих переменных модуля и функций. Тем путем я могу применить XmlUtil_I:: квалификация в отладчике для доступа к переменным. В этом случае '_I' отличает его от общедоступного пространства имен, такого как XmlUtil, который я могу хотеть использовать в другом месте.

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

11
ответ дан 6 December 2017 в 18:57
поделиться
Другие вопросы по тегам:

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