С++ пустой конструктор String

Я начинаю С++, поэтому извините, если вопрос слишком прост.

Я попытался собрать строковые константы и попробовать все их (запомнить их).

string strA();          // string(); empty string // incorrect
string strB("Hello");   // string( const char* str)
string strC("Hello",3); // string( const char* str, size_type length)
string strD(2,'c');     // string( size_type lenght, const char &c)
string strE(strB);      // string( const string& s)

cout << strA << endl;
cout << strB << endl;
cout << strC << endl;
cout << strD << endl;
cout << strE << endl;

Все они работают, за исключением strA. Он печатает "1". Почему? Какой тип strA в этом случае? Как я могу проверить тип материала, когда я не уверен?

Я заметил, что это правильный способ (который, по-видимому, несовместим с другими конструкторами, иногда parens иногда нет parens):

string strA;

ps: вопрос выделен жирным шрифтом, обычные нерелевантные ответы будут опущены.

Ответ 1

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

string strA();

эквивалентно

string strA(void);

прототип функции no-arg, которая возвращает строку.

Если вы хотите явно вызвать конструктор no-arg, попробуйте это:

string strA=string();

Это не полностью эквивалентно - это означает "создать временную строку, используя конструктор no-arg, а затем скопировать его для инициализации переменной strA", но компилятору разрешено оптимизировать его и опустить копирование.

EDIT: Вот подходящий элемент в С++ FAQ Lite

Ответ 2

Он считает, что

string strA();

как объявление функции.

Для конструктора по умолчанию используйте:

string strA;

Ответ 3

В С++, как и в C, существует правило, в котором говорится, что все, что выглядит как объявление, будет рассматриваться как объявление.

string strA();

выглядит как объявление функции, поэтому он рассматривается как один. Вам нужно:

string strA;

Ответ 4

Я не думаю, что в этом случае применяется правило "если это может быть объявление, принятое как объявление". Поскольку в дальнейшем обе вещи являются декларациями

string a;
string a();

Это объявление объекта, а другое - объявление функции. Это правило применяется в других случаях. Например, в этом случае:

string a(string());

В этом случае string() может означать две вещи.

  • Объявление неопределенного параметра функции
  • Выражение, создающее построенный по умолчанию string

Здесь применяется fule, а string() понимается так же, как и указанный параметр (имена не имеют значения в параметрах при объявлении функции)

string a(string im_not_relevant());

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

string a(string (*im_not_relevant)());

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

string a();

Таким образом, в этом контексте нет никакой двусмысленности, и, таким образом, она объявляет функцию. Поскольку string имеет определенный пользователем конструктор, вы можете просто опустить круглые скобки, и эффект остается таким же, как и предполагалось.

Ответ 5

Он печатает 1, потому что указатели на функции всегда преобразуются в числовые как true.

Ответ 6

tkopec прав, почему он не работает. Чтобы ответить на ваш второй вопрос, здесь, как вы проверяете тип:

template<typename TEST> void Error_() {
   TEST* MakeError = 1;
}

Вызывая Error_(StrA);, вы получите ошибку компиляции, и ваш компилятор, вероятно, скажет вам, что это произошло в Error_< std::basic_string<char, std::allocator<char> > (*)(void)>(std::basic_string<char, std::allocator<char> > (*)(void)) Теперь std:: basic_string > просто std::string, поэтому это действительно означает Error_< std::string (*)(void)> (std::string (*)(void)). Часть между '< > ' повторяется между '()' и что sype strA. В этом случае std::string (*)(void).

Ответ 7

Компилятор интерпретирует string strA() как прототип функции, которая принимает недействительные аргументы и возвращает объект типа string. Если вы хотите создать пустой объект с строкой, используйте string strA; (без paranthesis)