【问题标题】:invalid initialization of non-const reference of type 'const char*&' from an rvalue of type 'const char *'从“const char *”类型的右值对“const char*&”类型的非常量引用进行无效初始化
【发布时间】:2015-07-14 16:19:40
【问题描述】:

我做了一个 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);

它编译没有错误。

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

【问题讨论】:

  • 松开函数签名中的 &,它们不会添加任何内容。
  • 还有char *hello="hello"; ???即使你确实编译了它,它也会在你的函数中对只读内存进行无效写入。如果上述代码行编译时至少没有警告,您需要将警告级别提高到迂腐的高度。
  • @hoholee12: 嗯,首先,为什么你的参数通过引用传递???有很多方法可以“修复”您的代码。这就是为什么不知道你的意图是没有意义的。

标签: c++ reference constants reference-binding


【解决方案1】:

const char *&amp; 是对char const * 的非const 引用。 "bye bye" 的类型是char 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 调用还会尝试覆盖字符串文字,这又是未定义的行为。

调高编译器的警告级别,并注意警告。 g++ 使用-pedantic 为上面的行生成以下警告

警告:ISO C++ 禁止将字符串常量转换为 'char*' [-Wpedantic]

 char *hello="hello";
             ^

【讨论】:

    【解决方案2】:

    "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");
    }
    

    g++ 给出:

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

    【讨论】:

    • 所以,它不是 'const char*' 吗?
    • @hoholee12 它 convertsconst char*,它本身不是 const char*,因此对所述相同的引用是不合理的。
    • 嗯,我不确定我会称之为“文字数组”。这是一个字面量的数组。组件chars 是“文字”吗?没有把握。不这么认为。
    【解决方案3】:

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

    const char *bye="bye bye"; mystrcpy(hello, bye); 有效,因为bye 是一个指针变量,所以你可以引用它。

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

    您不需要在 mystrcpy 函数签名中引用 &amp; - 这只会使函数更难使用,并且如果您不小心调整函数中的指针(例如,如果您开始使用 @ 987654328@).

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多