1

我在以下代码中面临编译错误。我期望即使是临时对象也可以绑定到 const 引用。所以我想知道它应该是有效的代码。但是,g++ 给了我这个错误,而 clang 不会给我这样的错误。有没有人让我知道发生这种情况的确切原因?

#include <iostream>

struct TestClass
{
    TestClass() : str()
    {   
        strncpy(str, "hello", sizeof(str));
    }   

    char str[6];

    char (&getStr())[6]
    {   
        return str;
    }   
};

template <typename T>
void printFunc(const T& str)
{
    std::cout << str << std::endl;
}

int main()
{
    TestClass obj;
    printFunc(obj.str);
//  printFunc(TestClass().str);  // <- This line gives compilation error.
    printFunc(TestClass().getStr());
    return 0;
};
4

1 回答 1

4

我会假设您的 GCC 版本会忽略TestClass().str作为右值数组的事实(在 C 和 C++ 语言中都是非常奇特的东西)。当初始化器是右值时,参考初始化的细节中的某些内容实施不正确。显然,该错误已在以后的版本中得到修复。

同时obj.strTestClass().getStr()都是左值数组。它们由直接引用绑定的直接规则处理,因此不会出现问题。

要解决评论:

如果您将函数模板修改为

template <typename T> printFunc(const T str)

情况将发生巨大变化。现在它不再是一个引用绑定问题。现在数组到指针的转换规则接管了。

在您的原始版本中,类型T被推断为char [6],而在这个新版本中,类型被推断为char *。当参数传递给函数时,您的数组类型完全丢失:它是一个被传递的指针。这完全消除了引用绑定的原始问题,并使代码无论数组的左值还是右值都可以编译。

例如,您可以尝试sizeof str在函数内部打印并观察两个版本之间的差异。原始的将以字节(6)为单位打印您的数组大小,而新的将打印指针大小(4对于 ideone 的平台)。

于 2012-06-30T17:48:24.080 回答