C++ 类型为';的非常量引用的初始化无效;常量字符*&';从类型为';常量字符*';

C++ 类型为';的非常量引用的初始化无效;常量字符*&';从类型为';常量字符*';,c++,reference,constants,reference-binding,C++,Reference,Constants,Reference Binding,我做了一个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

我做了一个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;
}
它编译无误

我需要知道为什么前一个不起作用,谢谢。

“再见”不是指针,而是一个字符数组。它可以衰减为指针,但不可能将其作为指针的引用传递

您可以更改函数签名:

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");
}
#包括
模板
无效检查类型(T&)
{
静态断言(std::is_same::value,“inspect_type”);
}
int main()
{
检查类型(“再见”);
}
g++提供:

在“void inspect_type(const T&)[with T=const char[8]]的实例化中”

“bye-bye”不是指针,而是一个字符数组。它可以衰减为指针,但不可能将其作为指针的引用传递

您可以更改函数签名:

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");
}
#包括
模板
无效检查类型(T&)
{
静态断言(std::is_same::value,“inspect_type”);
}
int main()
{
检查类型(“再见”);
}
g++提供:

在“void inspect_type(const T&)[with T=const char[8]]的实例化中”

您的函数引用指针,这有点不寻常。值得注意的是,这意味着输入必须是一个有自己存储的指针(以便您可以引用指针)

const char*bye=“bye bye”;mystrcpy(你好,再见)
之所以有效,是因为
bye
是一个指针变量,所以您可以引用它

mystrcpy(hello,“bye-bye”)
失败,因为
“bye-bye”
不是指针-它是一个字符数组(const char[8]),因此没有可引用的指针

您不需要在
mystrcpy
函数签名中引用
&
,这只会使函数更难使用,并且如果您意外地调整函数中的指针(例如,如果您开始执行
*stuff++=*other++;
),可能会引入有趣的错误。

您的函数引用指针,这有点不寻常。值得注意的是,这意味着输入必须是一个有自己存储的指针(以便您可以引用指针)

const char*bye=“bye bye”;mystrcpy(你好,再见)
之所以有效,是因为
bye
是一个指针变量,所以您可以引用它

mystrcpy(hello,“bye-bye”)
失败,因为
“bye-bye”
不是指针-它是一个字符数组(const char[8]),因此没有可引用的指针


您不需要在
mystrcpy
函数签名中引用
&
,这只会使函数更难使用,如果您不小心调整了函数中的指针(例如,如果您开始执行
*stuff++=*other++;
),可能会引入有趣的错误.

常量字符*&
是对
常量字符*
的非
常量引用。
“再见”
的类型是
字符常量[8]
(大小包括终止的空字符)。对
mystrcpy
的调用将隐式地将
char const[8]
转换(或衰减)为
char const*
,但会生成一个右值指针,您无法将其绑定到非
const
引用参数

如果将函数签名更改为

void mystrcpy(char *&, const char * const&)
//                                  ^^^^^ const reference
您的代码将被编译。类似地,如果按值获取指针,代码将编译

void mystrcpy(char *, const char *)

一旦您修复了所有这些,您的代码将编译并可能在运行时崩溃,因为您有未定义的行为

char *hello="hello";
C++11禁止您将字符串文字转换为
char*
,这是C++03中不推荐的行为。不仅如此,您的
mystrcpy
调用还会尝试覆盖字符串文字,这也是未定义的行为

char *hello="hello";
打开编译器的警告级别,并注意警告。g++使用
-pedantic

警告:ISO C++禁止将字符串常量转换为'char * '- Wpedantic ] <
 char *hello="hello";
             ^

const char*&
是对
char const*
的非
const
引用。
“再见”
的类型是
字符常量[8]
(大小包括终止的空字符)。对
mystrcpy
的调用将隐式地将
char const[8]
转换(或衰减)为
char const*
,但会生成一个右值指针,您无法将其绑定到非
const
引用参数

如果将函数签名更改为

void mystrcpy(char *&, const char * const&)
//                                  ^^^^^ const reference
您的代码将被编译。类似地,如果按值获取指针,代码将编译

void mystrcpy(char *, const char *)

一旦您修复了所有这些,您的代码将编译并可能在运行时崩溃,因为您有未定义的行为

char *hello="hello";
C++11禁止您将字符串文字转换为
char*
,这是C++03中不推荐的行为。不仅如此,您的
mystrcpy
调用还会尝试覆盖字符串文字,这也是未定义的行为

char *hello="hello";
打开编译器的警告级别,并注意警告。g++使用
-pedantic

警告:ISO C++禁止将字符串常量转换为'char * '- Wpedantic ] <
 char *hello="hello";
             ^

松开&在函数签名中,它们不添加任何内容。和
char*hello=“hello”???即使您确实要编译它,它也会吐在函数中无效的写只读内存上。如果前面提到的行编译时没有至少一个警告,则您可以继续