C++ 为什么返回类型为';cv';被忽略了吗?
至少在“铿锵”和“GCC”中。以下是一个例子:C++ 为什么返回类型为';cv';被忽略了吗?,c++,c++11,constants,language-lawyer,return-type,C++,C++11,Constants,Language Lawyer,Return Type,至少在“铿锵”和“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”的第二行中,我们将返回值temporar
char *const InString(char *const p) {
return gets(p);
}
int main()
{
static char arr[260];
char * &&str = InString(arr); //compiles without error - what??????
}
正如大多数人可能知道的那样,在“main”的第二行中,我们将返回值temporary('prvalue')绑定到一个'rvalue reference'中,从而延长了它的生命周期。所以我的问题是这里发生了什么-返回值的“cv”真的被忽略了吗?如果是,在标准中这是在哪里写的,或者如何将'char*const&&
转换为'char*&&'
*需要ISOC++标准认证。< /P>
编辑:问题是在“C++11”之前,您不允许修改返回值,因为没有引入“R值”,还因为:
InString(arr) = nullptr;
没有意义。但是,现在您可以延长“返回值”的使用寿命,因此可以对其进行修改:
auto &&refRetVal = InString(arr);
refRetVal = nullptr;
因此,“const”返回“cv”可能很有用。如果上面'InString'的返回类型是'constant',那么对'nullptr'的第二次赋值将是非法的。返回类型中的cv限定符仅在第一级被忽略,因此int-const-foo()
等于int-foo()
但int-const&foo()
不等于int-foo()
在您的例子中,您的函数char*const InString()
相当于char*InString()
关于char*&&str=InString(arr)
的绑定。函数的返回是一个r值(临时值),而str
是一个r值引用,因此这是预期的。当然,临时的生存期也扩展到了引用的范围
顺便说一句,你的代码,用-Wextra
编译,在CLang++中给出:
警告:返回类型上的“const”类型限定符无效[-Wignored限定符]
在G++中:
警告:函数返回类型[-Wignored限定符]上的类型限定符被忽略
在考虑@dyp提到的报价后,即[expr]/6:
如果prvalue最初的类型为“cvT
,”其中T
是
cv非类、非数组类型,的类型
在进一步分析之前,将表达式调整为T
结论相当简单:由于表达式InString(…)
是一个PR值,InString(…)
(它是引用的初始值设定项)的类型被简单地调整为char*
,这显然是与引用的目标类型兼容的引用(也是char*
)。换句话说,在确定函数调用表达式的类型时,您添加的常量将被忽略(但在查看函数类型本身时,不会被忽略!)
但是,对于标量prvalues,引用从不直接绑定到初始值设定项表达式,而是初始化临时值并将引用绑定到它:
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
返回类型中的cv限定符仅在第一级被忽略,因此int-const-foo()
等于int-foo()
,但int-const&foo()
不等于int-foo()
。除此之外,我不知道你在问什么……我问的是返回值temporary'prvalue',从C++11开始,它的生命周期可以扩展,因此修改它变得很有用,因此'const'cv。@FISOCPP:总是可以通过右值表达式修改临时值(尽管我承认有一两个非常小的限制)这不是在C++ 11中新的。只是在你的例子中,你必须要篡改<代码> conconaskase>代码>,或者调用一个<代码>可变的成员函数来完成它,因为你只能把临时绑定到一个<代码> const REF。但是,如果你考虑一个简单的例子,比如“代码> STD::CUT。“C++ 11之前,您不允许修改返回值,因为ReValk没有被引入”——完全垃圾,C++总是有rValk,并且您可以随时修改返回值Valestand文件资格是我需要的。@ FISCOPP:我想您是指“C++标准引用/引用”。“。通常没有常量非类非数组类型的表达式。const
不会在返回类型上被忽略。请检查类类型。“通常没有常量非类非数组类型的表达式”对不起,我必须证明:没有非const,非数组类型的PROVALL表达式。是的,是真的。我没有从其他答案中得到这个。这个解释绝对是最好的。这确实是我在C++中遇到的最奇怪的规则之一。我想我在尝试绑定到一个类型为DE的LValk引用时已经学会了它。duced:auto&x=g();
如果g
返回一个常量非类类型,那么它就不起作用了。@dyp现在我觉得人们可以写一本关于引用初始化规则的小书了。每次我尝试提供分析时,它都会变得更复杂。(顺便说一句:谢谢你纠正我。:o))可能,原因是非类非数组类型的prvalues是不可变的-它们是值,而不是对象。即使我们尝试将它们绑定到右值引用,它们也不是直接绑定的,而是用它们初始化的对象。我认为非类非数组类型的PRValue被视为真值,而不是对象。是的,整个初始化主题相当复杂。最近,我认为函数左值出现在refinit中是因为没有函数类型的右值。它有时看起来像是语言中模糊部分的集合。