为什么对象副本要构造和销毁两次?

克里斯·古德达尔

为什么在下面的代码中出现一对“额外”的复制构造函数和破坏?

当Dingledong的构造函数将STL容器作为参数时,就会发生这种情况(我尝试过std :: vector和std :: list)。其他事情可能会发生吗?如果构造方法改为使用指针,则不会发生。如果我改为在堆上分配ding(Dingledong * ding = new Dingledong(v)),也不会发生这种情况。

#include <list>
#include <iostream>

class Dingledong{
public:
    Dingledong(std::list<int> numbers)
    {
        std::cout << "construction\n";
        numbers_ = numbers;
    }
    Dingledong(Dingledong const& other)
    {
        std::cout << "COPY construction\n";
    }
    ~Dingledong()
    {
        std::cout << "destructed\n";
        // I would do some cleanup here.. unsubscribe from events, whatever..
        // but the destructor is called sooner than I would expect and thus
        // the cleanup is done prematurely.
    }
    std::list<int> numbers_;
};

void diller()
{
    std::cout << "diller started.. " << std::endl;
    std::list<int> v = std::list<int>(34);
    // Having an STL container as parameter in constructor causes Dingledong's copy constructor to 
    // be used to create a temporary Dingledong which is immediately destructed again. Why?
    Dingledong ding = Dingledong(v);
    std::cout << "Has ding been destructed?\n";
}

int main()
{
    diller();
    system("pause");
}

输出:

diller started...
construction
COPY construction     // I didn't expect this to happen
destructed            // I didn't expect this to happen
Has ding been destructed?
destructed

先感谢您!

毫米

这段代码:

Dingledong ding = Dingledong(v);

方法:

  1. 创建类型为的临时对象Dingledong,使用初始化v
  2. 创建对象ding,使用临时对象初始化。

复制构造函数在此处进入步骤2。如果您不想要副本,请不要编写指定副本的代码。例如:

Dingledong ding(v);   // no copy

编译器可以实现一个称为复制省略的功能,其中可以优化此临时对象(即使复制构造函数具有副作用),但是它们不必这样做,在这种情况下,没有理由依赖于此。


您可以通过添加move-constructor来改进代码,在这种情况下(如果编译器不执行复制省略),该操作将是移动而不是复制,从而降低了成本。

也有你的构造一个浪费副本(numbers从复制v,然后numbers_从复制numbers,并且也numbers_被初始化,然后分配,而不是仅仅被初始化)。这将是一个更好的构造函数:

Dingledong(std::list<int> numbers): numbers_( std::move(numbers) )
{
    std::cout << "construction\n";
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么构造函数被两次调用

来自分类Dev

为什么列出两次时该对象消失了?

来自分类Dev

jQuery UI工具提示-“ my”和“ at”是什么意思?为什么要两次调用tooltip()?

来自分类Dev

Java 6:为什么要定义两次泛型?

来自分类Dev

为什么要尝试两次查找析构函数?

来自分类Dev

为什么基类的构造方法被调用两次?

来自分类Dev

为什么bean构造函数被调用两次?

来自分类Dev

为什么对象副本要构造和破坏两次?

来自分类Dev

AWS EB docker app:为什么要配置两次nginx?

来自分类Dev

在Angular2中,为什么在setTimeout之后要进行两次内容检查和查看?

来自分类Dev

为什么要两次拿东西?

来自分类Dev

为什么指定了生命周期管理器时,类型要注册两次?

来自分类Dev

JUNIT测试-为什么构造函数被两次调用

来自分类Dev

DNX为什么要两次运行代码

来自分类Dev

为什么要两次使用静态库来使编译工作正常进行?

来自分类Dev

为什么要两次声明jQuery?

来自分类Dev

Function.prototype.apply.apply-为什么要两次调用

来自分类Dev

为什么我的C ++程序的副本构造函数被调用两次?

来自分类Dev

为什么控制器要创建两次?

来自分类Dev

为什么构造函数被两次调用

来自分类Dev

为什么析构函数被调用两次而构造函数仅被调用一次?

来自分类Dev

为什么我的构造函数被两次调用

来自分类Dev

为什么列出两次时该对象消失了?

来自分类Dev

导入模块和子模块。为什么要进口两次?

来自分类Dev

为什么说明我要渲染两次或调用渲染两次?

来自分类Dev

为什么此数组构造两次?

来自分类Dev

为什么在Java中两次使用构造函数

来自分类Dev

为什么这个构造函数被调用两次?

来自分类Dev

为什么我需要指定对象类型两次?

Related 相关文章

  1. 1

    为什么构造函数被两次调用

  2. 2

    为什么列出两次时该对象消失了?

  3. 3

    jQuery UI工具提示-“ my”和“ at”是什么意思?为什么要两次调用tooltip()?

  4. 4

    Java 6:为什么要定义两次泛型?

  5. 5

    为什么要尝试两次查找析构函数?

  6. 6

    为什么基类的构造方法被调用两次?

  7. 7

    为什么bean构造函数被调用两次?

  8. 8

    为什么对象副本要构造和破坏两次?

  9. 9

    AWS EB docker app:为什么要配置两次nginx?

  10. 10

    在Angular2中,为什么在setTimeout之后要进行两次内容检查和查看?

  11. 11

    为什么要两次拿东西?

  12. 12

    为什么指定了生命周期管理器时,类型要注册两次?

  13. 13

    JUNIT测试-为什么构造函数被两次调用

  14. 14

    DNX为什么要两次运行代码

  15. 15

    为什么要两次使用静态库来使编译工作正常进行?

  16. 16

    为什么要两次声明jQuery?

  17. 17

    Function.prototype.apply.apply-为什么要两次调用

  18. 18

    为什么我的C ++程序的副本构造函数被调用两次?

  19. 19

    为什么控制器要创建两次?

  20. 20

    为什么构造函数被两次调用

  21. 21

    为什么析构函数被调用两次而构造函数仅被调用一次?

  22. 22

    为什么我的构造函数被两次调用

  23. 23

    为什么列出两次时该对象消失了?

  24. 24

    导入模块和子模块。为什么要进口两次?

  25. 25

    为什么说明我要渲染两次或调用渲染两次?

  26. 26

    为什么此数组构造两次?

  27. 27

    为什么在Java中两次使用构造函数

  28. 28

    为什么这个构造函数被调用两次?

  29. 29

    为什么我需要指定对象类型两次?

热门标签

归档