【问题标题】:Why does it look as if my object is destroyed twice?为什么我的对象看起来好像被销毁了两次?
【发布时间】:2014-07-11 07:13:24
【问题描述】:

我阅读了一些关于 C++ 中指针的内容,并且不应该将所有内容都创建为指针。为了进一步了解这一点并了解它是如何工作的,我编写了一个小程序:

一个main.cpp

#include <iostream>

#include "Master.h"

using namespace std;

int main()
{
    Master master = Master("master");

    master.printSlaves();

    return 0;
}

一个Master.h

class Master
{
public:
    Master(std::string name);

    ~Master();

    void printSlaves()
    {
        _slave1.printName();
        _slave2->printName();
    }

private:
    Slave   _slave1;
    Slave   *_slave2;

    std::string _name;
};

还有一个Master.cpp

#include "Master.h"

Master::Master(std::string name)
{
    std::cout << "Master() entered." << std::endl;
    _name = name;

    _slave2 = new Slave("slave2");
    _slave1 = Slave("slave1");

    std::cout << "\t" << _name << " created." << std::endl;

    std::cout << "Master() exited." << std::endl;

}

Master::~Master()
{
    std::cout << "\t" << _name << " destroyed." << std::endl;
}

Slave.h

class Slave
{
public:
    Slave()
    {

    }

    Slave(std::string name);

    void printName()
    {
        std::cout << "my name is " << _name << std::endl;
    }

    ~Slave();

private:
    std::string _name;
};

Slave.cpp

#include "Slave.h"

Slave::Slave(std::string name)
{
    std::cout << "Slave() entered." << std::endl;

    _name = name;

    std::cout << "\t" << _name << " created." << std::endl;

    std::cout << "Slave() exited." << std::endl;


}

Slave::~Slave()
{
    std::cout << "\t" << _name << " destroyed." << std::endl;
}

我期望的输出:

Master() entered. Slave() entered. slave2 created. Slave() exited. Slave() entered. slave1 created. Slave() exited. master created. Master() exited. my name is slave1 my name is slave2 master destroyed. slave1 destroyed.

但我得到了

Master() entered. Slave() entered. slave2 created. Slave() exited. Slave() entered. slave1 created. Slave() exited. **slave1 destroyed.** master created. Master() exited. my name is slave1 my name is slave2 master destroyed. **slave1 destroyed.**

显然我的slave1 被销毁了两次。我不明白为什么会这样,为什么这甚至是可能的。

谁能给我解释一下?

【问题讨论】:

  • 只是说,这是一个很好的问题,有一个很好的例子。
  • 因为奴隶制是非法的。
  • 实际上它比它需要的要冗长得多。
  • @LightnessRacesinOrbit,你是在谈论我的代码还是我的问题?代码有点膨胀。那是因为我很懒
  • @user2699453:是的,这就是问题所在。请不要偷懒。

标签: c++ pointers destructor


【解决方案1】:

问题出在一行

_slave1 = Slave("slave1");

为零件Slave("slave1");创建一个临时从站,然后分配给_slave1。赋值后,临时的Slave对象被销毁。

如果你写你的代码像

Master::Master(std::string name):_slave1("slave1")
{
 //other code
}

那么它只会被创建和销毁一次。

【讨论】:

  • 顺便提一下,如果启用优化,编译器可以省略(我希望这个词是对的)复制构造函数并直接初始化_slave1,就好像它是直接构造的一样。更多阅读:en.wikipedia.org/wiki/Copy_elision
  • @TheOne,这里使用了assignment 运算符,而不是copy constructor。要允许复制省略,你必须写 _slave1(Slave("slave1"));
  • 对于_slave2,您需要_slave2(new Slave("slave2"))。你也真的应该在Master的析构函数中delete_slave2
  • @user2699453,是的,就像Master::Master(std::string name):_slave1("slave1"), _slave2(new Slave("slave2"))
  • @user2699453,规则很简单,一个对象在超出范围时被销毁,无论你是显式创建它,还是它们是临时的。考虑通过将copy-constructorassignemnt-operator 设为私有(如果合适)使对象不可复制/可分配。为了防止内存泄漏,您可以在 C++11 中使用智能指针 (shared_ptr,unique_ptr)。您可以使用这些术语进行搜索。
猜你喜欢
  • 2016-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 2012-11-19
  • 1970-01-01
相关资源
最近更新 更多