auto_ptr_ref实现问题

时间:2013-07-23 20:25:47

标签: c++ stl

我已经查看了关于auto_ptr<>的内部实现的不同来源和auto_ptr_ref<&gt ;.我有这个问题,我无法弄明白为什么。

....当从函数返回'auto_ptr'时,编译器发现没有合适的ctor来复制构造返回的对象。但是转换为'auto_ptr_ref'并且ctor采用'auto_ptr_ref'构建'auto_ptr'。因此,编译器创建一个'auto_ptr_ref',它基本上只保存对原始'auto_ptr'的引用,然后从该对象构造一个'auto_ptr'。这就是全部(好吧,当返回一个对象时,编译器通常执行此过程两次,因为返回的值被复制到某个地方,但这不会改变过程).... (参考http://www.josuttis.com/libbook/auto_ptr.html

在此示例中,我模拟了auto_ptr<>的实现和auto_ptr_ref<>并且能够生成显示编译器确实经历进程两次

的结果

该示例具有以下基本特征:

1)A的复制构造函数不接受const引用。 2)A具有转换运算符B. 3)A有构造函数A(B);

class B {
};

class A {
public:

A () {
    printf("A default constructor() @ %p\r\n", this);
}

A(B) {
    printf("constructor(B) @ %p\r\n", this);
}
A (A &a) {
    printf("copy constructor(non-const) @ %p\r\n", this);
}

operator B() {
    printf("A convertion constructor(B) @ %p\r\n", this);
    return B();
}
};


A foo()
{
    return A();
}

int main()
{
    A a(foo());
}

所以当执行 A a(foo()))

1)foo()生成临时对象X. 2)X转换为B型 3)构造函数A(B)用于构造对象 a

这是输出:

A default constructor() @ 0xbfea340f
A convertion constructor(B) @ 0xbfea340f
constructor(B) @ 0xbfea344f
A convertion constructor(B) @ 0xbfea344f
constructor(B) @ 0xbfea344e

我们可以看到编译器通过转换构造步骤2和3两次。

为什么?

2 个答案:

答案 0 :(得分:1)

如果要调用返回类类型的函数,基本上会发生以下情况:

  • 在调用时,调用函数为堆栈上的临时返回值保留一些空间(它必须由调用函数完成,因为被调用函数在堆栈上分配的任何内容)一旦函数返回就会被释放)。它将该空间的地址传递给被调用的函数。

  • 在执行return语句时,被调用函数将赋予return语句的参数的返回值构造到调用函数提供的空间中。在您的情况下,该参数是临时A值。

  • 函数返回后,调用者使用被调用函数构造的临时值来执行代码所需的任何操作。在您的情况下,您可以使用它从中构造局部变量。

所以你从一个现有的两次构建一个A类型的新对象:首先,构造临时返回值(其生命时间在函数foo之后仍然存在从return语句中显式生成的临时返回(直到声明结束)(整个生命周期在完整表达式结束时结束,在这种情况下等同于从foo返回)。第二,从a返回的临时值初始化局部变量foo

当然,由于没有合适的复制构造函数,在两个情况下,您都会进行B次转换。这是有效的,因为return执行了直接初始化,而对于a,您明确编写了这样的直接初始化。

答案 1 :(得分:0)

正在创建类A 3次。一旦作为临时,并复制两次。其他编译器可能会根据其优化设置返回不同的结果。

return A()创建一个临时A,然后将其复制到返回的A第一次复制是第一次看到第2步和第3步。

然后A a(foo());foo()的返回值复制到main中的变量中。再次触发步骤2和3。