2014-09-30 2 views
11

Большую часть времени я вижу постоянные C-строки, определенные как:Правильный способ определения константы C-строки в C++?

static char const* MY_CONSTANT = "Hello World"; 

Однако самуказатель не const. Не было бы более уместным сделать это, как показано ниже?

static char const* const MY_CONSTANT = "Hello World"; 

Есть 2 цели с постоянными глобалов как это, я думаю:

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

Я просто предположил, что эти 2 цели были необходимы при определении постоянных строк.

Еще одна интересная вещь, что мне позволено это сделать:

int main() 
{ 
    auto MY_CONSTANT = ""; 
    MY_CONSTANT = "Another String"; 
} 

Это говорит мне, что auto выводит строку как char const* и не char const* const.

Так у меня есть два основных вопроса:

  1. Что является наиболее подходящим способом определить постоянные строки в стиле С (я полагаю, постоянные указатели-на-то, тем более общий вопрос?). Почему вы выбираете тот или иной?
  2. Что касается моего примера с auto, имеет смысл, почему он выбирает char const* (потому что это массив данных, который является постоянным, а не самим указателем). Могу ли я сделать auto вывод char const* const или я могу изменить код, чтобы он привел к такому типу?
+0

Не вы имеете в виду 'константный символ * const'? – Adam

+4

@Adam Обе формы действительны C++. Твоя делает то же, что и моя. –

+1

по умолчанию, что 'auto' определяет минимальное ограничение, что означает, что тот факт, что переменная не может быть переназначена, - это ваш выбор. вы можете сделать 'auto const', я полагаю, если хотите, но лучше не навязывать его всем. –

ответ

6

Ну если это действительно постоянная, то constexpr будет С ++ 11 способов сделать это:

constexpr char const* MY_CONSTANT = "Hello World"; 

Первый пример:

static char const* MY_CONSTANT = "Hello World"; 

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

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

Где статический делает разницу, например, если ли Вы хотите Const член быть за подчиненности или в классе:

class A 
{ 
     char const* const const_per_instance = "Other Const String"; 
    public: 
     constexpr static char const* const const_per_class = "Hello World" ; 
}; 

Если мы требуем Конст быть в классе, то мы должны использовать статические в противном случае нет.Пример немного изменится, если вы не можете использовать constexpr:

class A 
{ 
     char const* const const_per_instance = "Other Const String"; 
    public: 
     static char const* const const_per_class ; 
}; 

char const* const A::const_per_class = "Hello World" ; 

, но суть одна и та же просто синтаксис отличается.

Для вашего второго вопроса, как Gotw #92 говорит авто падает сверху сопзЬ уровня, один пример, приведенный следующим образом:

const int ci = val; 
auto  g = ci; 

и говорит:

Тип г является внутр.

Помните, что только потому, что ci const (только для чтения) не имеет , о том, хотим ли мы быть const. Это отдельная переменная. Если мы хотели г быть константными, мы сказали бы константное авто, как мы это делали в случае с выше

примера, который идет речь, заключается в следующем:

int   val = 0; 
//.. 
const auto c = val; 
+1

Печально constexpr не поддерживается на msvc 12 :-( –

+0

@ void.pointer вам не нужен * constexpr * ответ не меняет только синтаксис. Я обновил ответ, чтобы включить пример без * constexpr *. –

0

Это редкий случай, где это происходит, что вы перезаписать указатель, который указывает на константное значение, поэтому большинство разработчиков опустить второй сопзЬ но семантически было бы действительно правильно так:

static char const* const MY_CONSTANT = "Hello World"; 

или в таком виде:

static const char* const MY_CONSTANT = "Hello World"; 

constexpr для объявления просто необходима, если она является частью другой функции constexpr, как это:

static constexpr const char* const MY_CONSTANT = "Hello World"; 
static constexpr const char* Foo() 
{ 
    // ... 
    return MY_CONSTANT; 
} 
2
constexpr auto& MY_CONSTANT = "Hello World"; 
  • MY_CONSTANT имеет тип const char (&)[12]
  • Нет распада (граница массива не потеряна)
  • Все константа - сам массив и ссылка (по определению)
  • Все constexpr (может быть использована во время компиляции) - сам массив и ссылка
  • MY_CONSTANT имеет внутреннюю связь в связи с constexpr и может быть использована в заголовках
+0

С помощью VC++ 'static auto & MY_CONSTANT =« Hello World »;' можно использовать вместо этого. – user2665887

+0

'static' не имеет ничего общего с постоянством. Это означает, что функция не видна в других единицах компиляции. –

0

Хорошо сделано для того, чтобы заметить константу на указательной части! Многие люди этого не понимают.

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

Заголовок:

extern const char *const mystring;

источник:

extern const char *const mystring = "hello";

В качестве альтернативы

Заголовок:

extern const std::string mystring;

источник:

extern std::string mystring = "hello";

Смежные вопросы