为什么 return-type 'cv' 会被忽略?
Why return-type 'cv' is ignored?
至少在 'Clang' 和 'GCC' 中。这是一个例子:
char *const InString(char *const p) {
return gets(p);
}
int main()
{
static char arr[260];
char * &&str = InString(arr); //compiles without error - what??????
}
你们中的大多数人可能都知道,在 main'
的第二行中,我们将 return 临时值 ('prvalue') 绑定到 'rvalue reference' 从而延长其使用寿命。所以我的问题是这里发生了什么——return 值的 'cv' 真的被忽略了吗? ]?
*需要ISO C++标准认证。
编辑:问题是在 'C++ 11' 之前,您不允许修改 return 值,因为 'rvalues' 没有被引入,也因为类似的东西:
InString(arr) = nullptr;
毫无意义。但是现在您可以延长 'return-value' 生命周期,因此可以对其进行修改:
auto &&refRetVal = InString(arr);
refRetVal = nullptr;
从这里可以看出 'const' return 'cv' 很有用。如果上面 'InString' 的 return 类型是 'constant' 那么对 'nullptr' 的第二次赋值将是非法的。
return 类型中的 cv-qualifier 仅在第一层被忽略,因此 int const foo()
等于 int foo()
但 int const &foo()
不等于 int &foo()
.
在你的例子中,你的函数 char *const InString()
等同于 char *InString()
。
以及关于 char *&&str = InString(arr)
的绑定。函数的 return 是右值(临时值),而 str
是右值引用,所以这是意料之中的。当然,temporary的生命周期是延长到reference的范围内。
顺便说一句,你的代码,用 -Wextra
编译后在 CLang++ 中给出:
warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
在 G++ 中:
warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
在考虑@dyp 提到的引述后,即 [expr]/6:
If a prvalue initially has the type “cv T
,” where T
is a
cv-unqualified non-class, non-array type, the type of
the expression is adjusted to T
prior to any further analysis.
结论很简单:由于表达式 InString(..)
是纯右值,InString(..)
(引用的初始值设定项)的类型被简单地调整为 char*
,这显然与引用的目标类型兼容(也 char*
)。也就是说,你添加的const
在判断函数调用表达式的类型的时候只是简单的忽略了(但是是不忽略在查看 函数类型 本身时!)。
但是,对于标量纯右值,引用永远不会 直接 绑定到初始化表达式,而是初始化一个临时变量并将引用绑定到它:
int&& i = 4; // Temporary initialized with 4 and bound to i
int const f();
int&& ref = f(); // Initializer expression has type int - same as above
至少在 'Clang' 和 'GCC' 中。这是一个例子:
char *const InString(char *const p) {
return gets(p);
}
int main()
{
static char arr[260];
char * &&str = InString(arr); //compiles without error - what??????
}
你们中的大多数人可能都知道,在 main'
的第二行中,我们将 return 临时值 ('prvalue') 绑定到 'rvalue reference' 从而延长其使用寿命。所以我的问题是这里发生了什么——return 值的 'cv' 真的被忽略了吗? ]?
*需要ISO C++标准认证。
编辑:问题是在 'C++ 11' 之前,您不允许修改 return 值,因为 'rvalues' 没有被引入,也因为类似的东西:
InString(arr) = nullptr;
毫无意义。但是现在您可以延长 'return-value' 生命周期,因此可以对其进行修改:
auto &&refRetVal = InString(arr);
refRetVal = nullptr;
从这里可以看出 'const' return 'cv' 很有用。如果上面 'InString' 的 return 类型是 'constant' 那么对 'nullptr' 的第二次赋值将是非法的。
return 类型中的 cv-qualifier 仅在第一层被忽略,因此 int const foo()
等于 int foo()
但 int const &foo()
不等于 int &foo()
.
在你的例子中,你的函数 char *const InString()
等同于 char *InString()
。
以及关于 char *&&str = InString(arr)
的绑定。函数的 return 是右值(临时值),而 str
是右值引用,所以这是意料之中的。当然,temporary的生命周期是延长到reference的范围内。
顺便说一句,你的代码,用 -Wextra
编译后在 CLang++ 中给出:
warning: 'const' type qualifier on return type has no effect [-Wignored-qualifiers]
在 G++ 中:
warning: type qualifiers ignored on function return type [-Wignored-qualifiers]
在考虑@dyp 提到的引述后,即 [expr]/6:
If a prvalue initially has the type “cv
T
,” whereT
is a cv-unqualified non-class, non-array type, the type of the expression is adjusted toT
prior to any further analysis.
结论很简单:由于表达式 InString(..)
是纯右值,InString(..)
(引用的初始值设定项)的类型被简单地调整为 char*
,这显然与引用的目标类型兼容(也 char*
)。也就是说,你添加的const
在判断函数调用表达式的类型的时候只是简单的忽略了(但是是不忽略在查看 函数类型 本身时!)。
但是,对于标量纯右值,引用永远不会 直接 绑定到初始化表达式,而是初始化一个临时变量并将引用绑定到它:
int&& i = 4; // Temporary initialized with 4 and bound to i
int const f();
int&& ref = f(); // Initializer expression has type int - same as above