语法 question:what `char [5] const &` 是什么意思?
syntax question:what does `char [5] const &` mean?
char [5] const &
是什么意思?
对 5 个字符数组的常量左值引用
或对 5 个常量 char
数组的左值引用
或对 5 个字符的 const 数组的左值引用?
我正在阅读 C++ 编程语言书籍,并且我正在学习指向 char 的指针。我发现这段代码:char s[] = "Gorm";
,它提醒我字符串文字被隐式转换为 const char *
.
所以,我感到困惑,LHS 和 RHS 不是同一类型。
我使用在线编译器和 here 中的代码来了解编译器如何查看 LHS 和 RHS 的类型。然后,我发现 LHS 被视为 char[5]
而 RHS 被视为 char[5] const &
。
我可以解释 LHS 但是,我无法理解什么是 "constant lvalue reference to array of 5 char" 甚至在 LHS char s[]
隐式转换为 char* s
之后, "constant lvalue reference to non const pointer to non const char"是什么?
左值引用不是常量"it refers only to value initializing it"吗?那么,为什么我们在 &
之前需要 const
?
然后,不同类型的LHS和RHS如何分配?
下面是代码,我用来获取LHS和RHS的类型:
#include < type_traits >
#include < typeinfo >
#ifndef _MSC_VER
#include < cxxabi.h >
#endif
#include < memory >
#include < string >
#include < cstdlib >
#include < iostream > // std::cout
template < class T > std::string
type_name() {
typedef typename std::remove_reference < T >:: typeTR;
std::unique_ptr < char, void( *)(void *) > own(#ifndef _MSC_VER abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr), #else nullptr, #endif std::free);
std::string r = own != nullptr
? own.get()
: typeid(TR).name();
if (std::is_const < TR >:: value)
r += " const";
if (std::is_volatile < TR >:: value)
r += " volatile";
if (std::is_lvalue_reference < T >:: value)
r += "&";
else if (std::is_rvalue_reference < T >:: value)
r += "&&";
return r;
}
int & foo_lref();
int && foo_rref();
int foo_value();
int main() {
int i = 0;
const int ci = 0;
char s[] = "Gorm";
std::cout << "decltype(s) is " << type_name < decltype("Gorm") > () << '\n';
std::cout << "decltype(i) is " << type_name < decltype(i) > () << '\n';
std::cout << "decltype((i)) is " << type_name < decltype((i)) > () << '\n';
std::cout << "decltype(ci) is " << type_name < decltype(ci) > () << '\n';
std::cout << "decltype((ci)) is " << type_name < decltype((ci)) > () << '\n';
std::cout << "decltype(static_cast<int&>(i)) is " << type_name < decltype(static_cast < int &> (i)) > () << '\n';
std::cout << "decltype(static_cast<int&&>(i)) is " << type_name < decltype(static_cast < int &&> (i)) > () << '\n';
std::cout << "decltype(static_cast<int>(i)) is " << type_name < decltype(static_cast < int > (i)) > () << '\n';
std::cout << "decltype(foo_lref()) is " << type_name < decltype(foo_lref()) > () << '\n';
std::cout << "decltype(foo_rref()) is " << type_name < decltype(foo_rref()) > () << '\n';
std::cout << "decltype(foo_value()) is " << type_name < decltype(foo_value()) > () << '\n';
}
but i can not understand what is "constant lvalue reference to array of 5 char"
这是用词不当;它是对常量数组的引用,而不是对数组的常量引用。正如您所观察到的,引用无法更改,并且 const 不能应用于它们(因为它们不是对象)。
and then how can lhs and rhs of different types be assigned?
您可以从非 const 对象的值创建对 const 对象的引用。这是有道理的,因为您正在将读写的 "view" 转换为 "read-only."
要消除与 "weird" 类型的混淆,了解如何阅读它们很重要。 clockwise/spiral method is one way to go here. Another effective method is the right/left sweep method。虽然这些规则在有命名类型时效果最好,但仍然可以通过简单地从右到左阅读来调整它。
因此,char[5] const &
是一个 [n 左值] 对大小为 5 个字符的常量数组的引用。这听起来像是对字符串文字的准确描述。说数组是常量,只是意味着内容不能改变,字符串文字也是如此。
作为另一个例子,考虑一个数组:int arr[5]
。您可以更改数组的内容,但 arr
必须 始终 指向第一个元素,这意味着指针不能更改。声明一个始终指向同一事物的指针是通过以下方式完成的:int * const ptr;
。我可以改变我指向的值,但我不能改变我指向的地方。如果我声明它const int * const ptr
或int const * const ptr
,我不能改变我指向的值,也不能改变我指向的地方。
char [5] const &
不是有效类型。如果您发布的代码为您提供此输出,则代码已损坏。
检查类型是否有效的方法如下:
using type = char [5] const &; // error: expected ';' before 'const'
字符串文字的实际类型是const char [N]
,但在这种情况下无关紧要。
C++ 有一个特殊的规则,允许用字符串文字初始化字符数组。就这些了。
请注意,如果您将 decltype
应用于字符串文字,它将为您提供 const char (&)[N]
(对 char
的常量数组的引用)。但这不是文字的实际类型。
这听起来可能令人困惑,但表达式从来没有引用类型。变量可以,但表达式不行。参见:What expressions yield a reference type when decltype is applied to them?
如果 decltype
(应用于表达式而非变量时)为您提供左值引用类型,则表明该表达式是左值。 (右值引用表示一个 xvalue,缺少引用表示一个 prvalue)。
char [5] const &
是什么意思?
对 5 个字符数组的常量左值引用
或对 5 个常量 char
数组的左值引用
或对 5 个字符的 const 数组的左值引用?
我正在阅读 C++ 编程语言书籍,并且我正在学习指向 char 的指针。我发现这段代码:char s[] = "Gorm";
,它提醒我字符串文字被隐式转换为 const char *
.
所以,我感到困惑,LHS 和 RHS 不是同一类型。
我使用在线编译器和 here 中的代码来了解编译器如何查看 LHS 和 RHS 的类型。然后,我发现 LHS 被视为 char[5]
而 RHS 被视为 char[5] const &
。
我可以解释 LHS 但是,我无法理解什么是 "constant lvalue reference to array of 5 char" 甚至在 LHS char s[]
隐式转换为 char* s
之后, "constant lvalue reference to non const pointer to non const char"是什么?
左值引用不是常量"it refers only to value initializing it"吗?那么,为什么我们在 &
之前需要 const
?
然后,不同类型的LHS和RHS如何分配?
下面是代码,我用来获取LHS和RHS的类型:
#include < type_traits >
#include < typeinfo >
#ifndef _MSC_VER
#include < cxxabi.h >
#endif
#include < memory >
#include < string >
#include < cstdlib >
#include < iostream > // std::cout
template < class T > std::string
type_name() {
typedef typename std::remove_reference < T >:: typeTR;
std::unique_ptr < char, void( *)(void *) > own(#ifndef _MSC_VER abi::__cxa_demangle(typeid(TR).name(), nullptr, nullptr, nullptr), #else nullptr, #endif std::free);
std::string r = own != nullptr
? own.get()
: typeid(TR).name();
if (std::is_const < TR >:: value)
r += " const";
if (std::is_volatile < TR >:: value)
r += " volatile";
if (std::is_lvalue_reference < T >:: value)
r += "&";
else if (std::is_rvalue_reference < T >:: value)
r += "&&";
return r;
}
int & foo_lref();
int && foo_rref();
int foo_value();
int main() {
int i = 0;
const int ci = 0;
char s[] = "Gorm";
std::cout << "decltype(s) is " << type_name < decltype("Gorm") > () << '\n';
std::cout << "decltype(i) is " << type_name < decltype(i) > () << '\n';
std::cout << "decltype((i)) is " << type_name < decltype((i)) > () << '\n';
std::cout << "decltype(ci) is " << type_name < decltype(ci) > () << '\n';
std::cout << "decltype((ci)) is " << type_name < decltype((ci)) > () << '\n';
std::cout << "decltype(static_cast<int&>(i)) is " << type_name < decltype(static_cast < int &> (i)) > () << '\n';
std::cout << "decltype(static_cast<int&&>(i)) is " << type_name < decltype(static_cast < int &&> (i)) > () << '\n';
std::cout << "decltype(static_cast<int>(i)) is " << type_name < decltype(static_cast < int > (i)) > () << '\n';
std::cout << "decltype(foo_lref()) is " << type_name < decltype(foo_lref()) > () << '\n';
std::cout << "decltype(foo_rref()) is " << type_name < decltype(foo_rref()) > () << '\n';
std::cout << "decltype(foo_value()) is " << type_name < decltype(foo_value()) > () << '\n';
}
but i can not understand what is "constant lvalue reference to array of 5 char"
这是用词不当;它是对常量数组的引用,而不是对数组的常量引用。正如您所观察到的,引用无法更改,并且 const 不能应用于它们(因为它们不是对象)。
and then how can lhs and rhs of different types be assigned?
您可以从非 const 对象的值创建对 const 对象的引用。这是有道理的,因为您正在将读写的 "view" 转换为 "read-only."
要消除与 "weird" 类型的混淆,了解如何阅读它们很重要。 clockwise/spiral method is one way to go here. Another effective method is the right/left sweep method。虽然这些规则在有命名类型时效果最好,但仍然可以通过简单地从右到左阅读来调整它。
因此,char[5] const &
是一个 [n 左值] 对大小为 5 个字符的常量数组的引用。这听起来像是对字符串文字的准确描述。说数组是常量,只是意味着内容不能改变,字符串文字也是如此。
作为另一个例子,考虑一个数组:int arr[5]
。您可以更改数组的内容,但 arr
必须 始终 指向第一个元素,这意味着指针不能更改。声明一个始终指向同一事物的指针是通过以下方式完成的:int * const ptr;
。我可以改变我指向的值,但我不能改变我指向的地方。如果我声明它const int * const ptr
或int const * const ptr
,我不能改变我指向的值,也不能改变我指向的地方。
char [5] const &
不是有效类型。如果您发布的代码为您提供此输出,则代码已损坏。
检查类型是否有效的方法如下:
using type = char [5] const &; // error: expected ';' before 'const'
字符串文字的实际类型是const char [N]
,但在这种情况下无关紧要。
C++ 有一个特殊的规则,允许用字符串文字初始化字符数组。就这些了。
请注意,如果您将 decltype
应用于字符串文字,它将为您提供 const char (&)[N]
(对 char
的常量数组的引用)。但这不是文字的实际类型。
这听起来可能令人困惑,但表达式从来没有引用类型。变量可以,但表达式不行。参见:What expressions yield a reference type when decltype is applied to them?
如果 decltype
(应用于表达式而非变量时)为您提供左值引用类型,则表明该表达式是左值。 (右值引用表示一个 xvalue,缺少引用表示一个 prvalue)。