я сделал функцию mystrcpy,
void mystrcpy(char *&stuff, const char *&otherstuff){
for(int i=0; stuff[i]&&other[i]; i++){
stuff[i]=other[i];
}
}
и основная функция:
int main(){
char *hello="hello";
mystrcpy(hello, "bye bye"/*<--i have no clue what data type this really is!!*/);
printf("%s\n", hello);
return 0;
}
он не компилируется и говорит «неверная инициализация неконстантной ссылки типа» const char *&’из значения типа’ const char * ‘»…
когда я просто делаю:
const char *bye="bye bye";
mystrcpy(hello, bye);
компилируется без ошибок.
Мне нужно знать, почему первый не работает, спасибо.
Ваша функция занимает ссылка на указатель, что немного необычно. В частности, это означает, что входные данные должны быть указателем, который имеет свое собственное хранилище (чтобы вы могли взять ссылку на указатель).
const char *bye="bye bye"; mystrcpy(hello, bye);
работает потому что bye
является переменной указателя, так что вы можете взять ссылку на нее.
mystrcpy(hello, "bye bye")
не удается, потому что "bye bye"
является не указатель — это массив символов ( const char [8]
) и поэтому нет указателя для ссылки.
Вам не нужна ссылка &
в вашем mystrcpy
сигнатура функции — это просто усложняет использование функции и может привести к появлению интересных ошибок, если вы случайно отрегулируете указатели в функции (например, если вы начали делать *stuff++ = *other++;
).
const char *&
это неconst
ссылка на char const *
, Тип "bye bye"
является char const[8]
(размер включает в себя завершающий нулевой символ). Ваш звонок в mystrcpy
будет неявное преобразование (или распад) char const [8]
к char const *
, но это создает указатель rvalue, который вы не можете привязать кconst
эталонный параметр.
Если вы измените свою подпись функции на
void mystrcpy(char *&, const char * const&)
// ^^^^^ const reference
ваш код скомпилируется. Точно так же, если вы возьмете указатель (и) по значению, ваш код скомпилируется
void mystrcpy(char *, const char *)
Как только вы исправите все это, ваш код будет скомпилирован и, возможно, потерпит крах во время выполнения, потому что у вас неопределенное поведение.
char *hello="hello";
C ++ 11 запрещает вам преобразовывать строковый литерал в char *
и было объявлено устаревшим поведение в C ++ 03. Не только это, но ваш mystrcpy
Затем call пытается перезаписать строковый литерал, что снова является неопределенным поведением.
Увеличьте уровень предупреждений вашего компилятора и обратите внимание на предупреждения. g ++ выдает следующее предупреждение для строки выше с -pedantic
предупреждение: ISO C ++ запрещает преобразовывать строковую константу в ‘char *’ [-Wpedantic]
char *hello="hello"; ^
«пока» не указатель, а массив символов. Он может распадаться на указатель, но невозможно передать его как ссылку на указатель.
Вы можете изменить сигнатуру функции:
void mystrcpy(char *stuff, const char *otherstuff)
Если вы хотите проверить тип во время компиляции, вы можете использовать статическое утверждение, генерирующее ошибку компилятора:
#include <type_traits>
template <typename T>
void inspect_type(T&)
{
static_assert(std::is_same<T, void>::value, "inspect_type");
}
int main()
{
inspect_type("bye bye");
}
g ++ дает:
В экземпляре ‘void inspect_type (const T&) [с T = const char [8]] ’
…