Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么返回类型为';cv';被忽略了吗?_C++_C++11_Constants_Language Lawyer_Return Type - Fatal编程技术网

C++ 为什么返回类型为';cv';被忽略了吗?

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

至少在“铿锵”和“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”的第二行中,我们将返回值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最初的类型为“cv
T
,”其中
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中是因为没有函数类型的右值。它有时看起来像是语言中模糊部分的集合。