如何以正式和严格的方式定义(解释)C ++中的引用类型是什么?
我尝试谷歌,并研究了Stroustrup" The C ++ Programming Language",但我没有看到这个概念的定义。
答案 0 :(得分:2)
引用是别名,是对象的备用名称。它本身不是一个对象(并且以这种方式不是一个指针,即使它们的一些用途与指针的使用重叠)。
参考文献对其处理有一定的限制,与其非对象性有关。例如,您无法创建引用数组。它们必须在声明后立即初始化(绑定,就位),因为它们可能不存在别名的对象。
然而,您可以存储它们,并且它们遵守自动变量或成员变量的规则。他们的一个用途是通过C ++的值传递函数调用。
请注意,const引用具有作为别名的简洁副作用:当绑定到临时(即未命名)对象时,它们为所述对象赋予名称,因此将其生命周期延长到引用本身的生命周期。
{ // Block scope
Foo fooVal = makeFoo(); // Say makeFoo() returns a (temporary, unnamed) Foo
// Here the temporary Foo is dead (fooVal is a copy).
// Foo &fooRef = makeFoo(); // Error, reference is non-const
Foo const &fooCRef = makeFoo(); // All good
// ...
// The second temporary is still alive
fooCRef.doSomethingFunny(); // Works like a charm !
} // The second temporary dies with fooRef
但要注意,有可能(虽然设法)让对象超出范围,引用仍然指向它。然后,您将拥有悬空引用,这些引用不再被使用(这样做将是未定义的行为)。
Foo *fooPtr = new Foo; // Here is a Foo
Foo &fooRef = *fooPtr; // Here is an alias for that Foo
delete fooPtr; // Here is the end of that Foo's life
fooRef.doSomethingFunny(); // Here comes trouble...
答案 1 :(得分:1)
关于
“如何以正式和严格的方式定义(解释)C ++中的引用类型是什么?
C ++ 11标准在其
中给出了引用类型的以下正式和严格定义§8.3.2/ 1
“在声明T D中,其中D具有任何一种形式
&
attribute-specifier-seq optD1
&&
attribute-specifier-seq optD1
并且声明T D1
中的标识符类型是“ derived-declarator-type-listT
”,然后是类型D
的标识符是“ derived-declarator-type-list 对T
的引用。”
但是,如果您对C ++引用实际上更感兴趣(除了该术语的口语使用),那么请在表达式中检查其含义的定义,
§5.5
“如果表达式最初具有”
T
引用“类型(8.3.2,8.5.3),则类型将在T
之前调整为const
进一步的分析。表达式指定由引用表示的对象或函数,以及 表达式是左值或x值,具体取决于表达式
实际上,这意味着引用充当别名。
您可以将引用视为自动解除引用的{{1}}指针,它解释了大多数行为,但引用不一定占用存储(编译器可能能够完全优化它)。 / p>
答案 2 :(得分:0)
C和C ++之间的主要区别(除了对象和类!)是引用。 引用就像是指向变量的const指针。分配引用有点像使用指针,但使用&不*并且你不需要区别。区别在于您为指针分配地址,但为引用变量分配变量。 下面的行表明a的值被复制到aref中。但它不是,而是aref是对变量a的引用。一旦分配,aref与a相同。对aref的任何更改都会更改为以下示例
int& aref = a;
#include <stdio.h>
#include "stdafx.h"
int main()
{
int a=9;
int & aref = a;
a++;
cout << "The value of a is %i\n" << aref;
return 0;
}
还要记住
引用必须始终引用某些内容。不允许使用NULL。
创建时必须初始化引用。未分配的引用不可存在。
初始化后,无法将其更改为其他变量。
如果有帮助,请通知我,thanx
答案 3 :(得分:0)
根据一些专家的观点,引用类型本身不是C ++引用,而是与值类型相反。我给出了两个略有不同的定义-值类型和引用类型。
https://abseil.io/blog/20180531-regular-types
第一个是Titus Winters的博客帖子,他是负责C ++标准库的C ++小组委员会主席。
根据泰特斯·温特斯(Titus Winters)的观点,值类型和引用类型之间的区别在于复制行为。复制值类型时,将获得两个独立的对象,这些对象首先相等,但是在修改二者之一后可能会有所不同。复制引用类型时,将获得两个对象,它们引用相同的数据。
引用类型不拥有其数据。有些引用类型允许修改引用的数据(例如,跨度),有些则不允许(例如,string_view)。给出的两个示例对于传递函数参数都非常有用。函数的调用者确保在函数调用期间不会破坏引用类型的基础数据(就像普通C ++引用一样)。
https://docs.microsoft.com/en-us/cpp/cpp/value-types-modern-cpp?view=vs-2019
Microsoft文档将引用类型与多态类型(具有至少一个虚函数或成员变量的类型)同义,并将值类型作为非多态类型。 (非多态类型被Bjarne Stroustrup称为具体类型。)
值类型与内存和布局控制有关,引用类型与标识有关。
值类型允许编译器直接访问成员,由于运行时多态性,引用类型需要间接访问。
根据Microsoft的引用类型是不可复制的(以防止切片)。
所以语义有所不同,因为泰特斯·温特斯(Titus Winters)通过引用类型的实际复制行为来定义引用类型。