我应该对由构造函数中的运算符初始化的对象成员使用 "delete" "new"?



我有一个关于newdelete的问题:我是否应该使用delete作为输入参数或成员对象,例如:

https://github.com/jwbecalm/Head-First-Design-Patterns-in-CPP/blob/main/ch01_Strategy/main.cpp

应该在new FlyNewWay()分配的对象上使用delete吗?

// change behavior in runtime
mallardDuck->setFlyBehavior(new FlyNewWay());
// create custom MallarDuck on stack.
MallarDuck rocketDuck =  MallarDuck(new FlyWthRocket(), new NewQuack());

和在MallardDuck构造函数中:

https://github.com/jwbecalm/Head-First-Design-Patterns-in-CPP/blob/main/ch01_Strategy/MallarDuck.cpp

MallarDuck:: MallarDuck(){
cout << "in MallarDuck:: MallarDuck()" << endl;
// 为MallarDuck 赋值其特有的行为
m_flyBehavior = new FlyWithWings();
m_quackBehavior = new SimpleQuack();
}
我应该使用delete来释放m_flyBehaviorm_quackBehavior吗?但这两个都是object的成员。

我可以很容易地在MallarDuck的析构函数中添加delete

MallarDuck::~MallarDuck(){
cout << "in ~MallarDuck()" << endl;
delete m_flyBehavior;   
delete m_quackBehavior;
}

但是第一个代码块中提到的输入参数呢?还是不推荐这种设计和传递价值的方式?你有什么建议吗?

setFlyBehavior()如下,如果我添加删除fb,它将删除m_flyBehavior也为我的理解,因为fb和m_flyBehavior都指向相同的内存地址。

void Duck::setFlyBehavior(FlyBehavior* fb){
m_flyBehavior = fb;
cout << "in Duck::setFlyBehavior()" <<endl;
}

setFlyBehavior()之后的, fb和m_flyBehavior都指向相同的内存地址。所以在解构器:~MallarDuck()中,如果我删除m_flyBehavior,它指向的输入参数fb也将是自由的。因此,在解构器~MallarDuck()中删除就足够了。thx .

是当你使用new关键字分配一些内存时,你必须总是使用delete在以后不再需要的时候释放内存。否则,您将出现内存泄漏,就像您的程序一样。在你的例子中,你应该在MallarDuck.cpp的析构函数中使用delete

另一个解决方案是使用像unique_ptr这样的智能指针,这样你就不必显式地释放内存。

unique_ptr的语法类似于:

unique_ptr<FlyWithWings> m_flyBehavior(new FlyWithWings());

如果您对是否存在内存泄漏感到困惑,您可以在FlyWithWingsSimpleQuack的析构函数中添加cout语句,以确认是否在这些对象上调用析构函数。因此,如果需要的话,可以使用智能指针。

确认是否存在内存泄漏的步骤

  1. FlyWithWingsSimpleQuack的析构函数中增加一些std::cout<<"destructor ran;语句
  2. 同样,在这种情况下,不要在MallarDuck的析构函数中的数据成员上显式地使用delete
  3. 然后,如果你看到析构函数没有在数据成员m_flyBehaviorm_quackBehavior上运行,这将意味着你有内存泄漏,你需要在MallarDuck的析构函数中显式地在适当的数据成员上使用delete

回答你的编辑

第一个代码块中提到的输入参数如何?

对于语句mallardDuck->setFlyBehavior(new FlyNewWay());,可以使用以下代码:
void Duck::setFlyBehavior(FlyBehavior* fb){
//delete the old memory but note again we should check whether the pointer is valid or not
//check for a valid pointer
if (m_flybehavior)
{

delete m_flybehavior;//free the old memory
}

m_flyBehavior = fb;//so m_flybehavior points to some new memory
//no need to use delete now on m_flybehavior because  in the destructor ~MallarDuck() you have delete m_flybehavior
cout << "in Duck::setFlyBehavior()" <<endl;
}

对于语句

MallarDuck rocketDuck =  MallarDuck(new FlyWthRocket(), new NewQuack());

因为MallarDuck的析构函数有delete作为数据成员,它将释放该内存。此外,这假定输入参数已分配给数据成员。

所有使用new创建的指针必须在某个时候删除。在c++中,你通常不会给像setFlyBehavior()这样的函数一个指针,因为谁应该删除指针并不明显。然而,似乎你正在使用多态性,所以你需要使用某种指针。

如果函数像setFlyBehavior(new FlyNewWay())那样被调用,类应该删除指针。但是用户也可以用一个现有的指针调用它,然后删除它。该指针将被多次删除。

// Incorrect usage
FlyBehavior* way = new FlyNewWay();
duck1->setFlyBehavior(way);
duck2->setFlyBehavior(way);
delete way;

你的类无法知道用户是如何创建指针的。您不应该相信类正在被正确地使用。相反,将std::unique_ptr<FlyBehavior>作为参数并保存在您的类中。

std::make_unique:

创建参数
mallardDuck->setFlyBehavior(std::make_unique<FlyNewWay>());

相关内容

  • 没有找到相关文章

最新更新