7

我一直在阅读“C++ 入门”。对于对象的初始化,C++ 支持 2 种初始化形式:直接和复制。但是书上没有提到初始化的参考。在书中,我从未见过引用的直接初始化(如果存在)。一切都是副本,例如:

int i;
int &j = i;//but not int &j(i);which also works in my experiment

我想知道在下面进行引用的初始化是否相同。对于以下代码:

string null_book = "9-999-99999-9";

初始化过程是首先创建一个临时字符串对象tmp(例如),它将直接使用ac样式字符串参数进行初始化,然后使用复制构造函数初始化变量null_book。这对我来说很有意义。对于这个:

int &j = i;

ref j 会以同样的方式初始化吗?这将是一个临时引用,它 &t(例如)由 i 初始化,然后用 t 初始化 j?这没有意义???为什么书中从不使用直接初始化作为参考?感谢您的关注!

4

3 回答 3

7

直接初始化和复制初始化之间的主要区别在标准的第 8.5 节第 17 段中介绍。一般来说,不同之处在于,对于复制初始化中的类类型,不考虑显式构造函数(仅考虑转换构造函数),并制作可能省略的副本;在直接初始化中,考虑显式构造函数并直接构造目标。从标准的第 8.5 节:

[ =...]

对于非类类型(包括引用),直接初始化和复制初始化具有相似的语义;对于引用,在任何一种情况下都会发生引用绑定,如8.5.3 References [dcl.init.ref]中所述。引用的直接初始化和复制初始化仅在涉及转换函数的情况下具有不同的语义(13.3.1.6 Initialization by conversion function for direct reference binding [over.match.ref]);同样,允许直接初始化调用显式转换函数,而复制初始化则不允许。

所以,在

int &j = i;

8.5.3p5 适用,并且引用j直接绑定到 lvalue i。不调用任何临时对象。

就复杂性而言,引用更接近于基本(原始)类型而不是类类型。基元在没有临时构造的情况下被初始化(8.5p17,最后一个项目符号),一般参考也是如此。这可能就是为什么本书只使用=表格来初始化引用的原因;与原语一样,通常没有区别,而且书写int i = x;通常比int i(x);.

于 2012-12-19T13:03:55.897 回答
4

术语复制初始化直接初始化是C++语法的一部分。他们不会立即告诉你发生了什么样的代码生成。标准描述了任何语法结构的含义,初始化的上下文有许多不同的特定结果,具体取决于正在初始化的事物的类型。

特别是对于原始类型、指针类型和引用类型,直接初始化和复制初始化(语法结构!)具有完全相同的效果。也就是说,基本类型和指针类型使用初始化器的值进行初始化,并且引用绑定到初始化器所引用的对象:

int a1 = 5;
int a2(5);      // same thing

Foo * p1 = &x;
Foo * p2(&x);   // same thing

Bar & b1 = y;
Bar & b2(y);    // same thing

(然而,对于用户定义的类型,直接初始化和复制初始化有区别的,尽管它是一个微妙的区别,通常并不重要。)

于 2012-12-19T13:08:29.353 回答
3

C++ 中的引用只是一个戴着滑稽帽子的指针。该声明:

TYPE& x = y;

总是等价于:

TYPE* const x = &y;

所有引用所做的只是节省您输入*字符并声明您相信永远不会有空值。所以初始化是微不足道的,因为它是一个指针的初始化,而不是一个对象,并且没有复杂的对象,临时的或其他的,需要处理。

这是概念模型;当然,还有优化。如果您声明如下函数:

void takeARef(FOO const& ref) { ... }

并调用它,然后编译器只是将指针传递给函数,并且什么都不创建。

于 2012-12-19T12:58:15.520 回答