C ++ пустой String конструктор - PullRequest
16 голосов
/ 29 мая 2009

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

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

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 в этом случае? Как я могу проверить тип вещей, когда я не уверен?

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

string strA;

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

Ответы [ 7 ]

32 голосов
/ 29 мая 2009

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

string strA();

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

string strA(void);

прототип функции без аргументов, которая возвращает строку.

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

string strA=string();

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

EDIT: Вот соответствующий пункт в C ++ FAQ Lite

13 голосов
/ 29 мая 2009

считает

string strA();

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

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

string strA;
6 голосов
/ 29 мая 2009

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

string strA();

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

string strA;
4 голосов
/ 29 мая 2009

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

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 имеет определяемый пользователем конструктор, вы можете просто опустить скобки, и эффект останется таким же, как и предполагалось.

3 голосов
/ 29 мая 2009

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

2 голосов
/ 29 мая 2009

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)). Часть между '<>' повторяется между '()', и это тип strA. В этом случае std::string (*)(void).

1 голос
/ 29 мая 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...