С++ пустой конструктор 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)