是否需要删除未实例化为变量的指针?

时间:2016-08-09 16:40:45

标签: c++ oop c++11 pointers

我有一个Base类,有两个派生类DerivedADerivedB以及一个返回指针Base*的工厂方法。

Base* GetClass(int choice)
{
    if (choice == 0)
        return new DerivedA();
    else if (choice == 1)
        return new DerivedB();
    throw std::invalid_argument("no no no");
}

DerivedADerivedB都实现了一个方法,比如说GetDouble(),这个方法是我唯一感兴趣的是构建这些类中的任何一个:

double d = GetClass(0)->GetDouble();

我的问题是:当我调用GetClass(0)时,我创建了一个应该被删除的指针。但是,我没有将它实例化为一个对象。我还需要删除它吗?

类似的东西:

Base* c = GetClass(0);
double d = c->GetDouble();
delete c;

如何使用std::unique_ptr

提前谢谢。

PS:我认为有相关问题,例如thisthis,但我的更具体。

5 个答案:

答案 0 :(得分:8)

使用std::unique_ptr,您可以轻松调用delete

std::unique_ptr<Base> GetClass(int choice)
{
    if (choice == 0)
        return std::make_unique<DerivedA>();
    else if (choice == 1)
        return std::make_unique<DerivedB>();
    throw std::invalid_argument("no no no");
}

您现在可以安全地致电:

double d = GetClass(0)->GetDouble();

这里发生的是:GetClass(0)将返回rvalue只会在;销毁的GetClass(0)->func->func->etc();。因此,GetClass()之类的链式调用仍会使;返回的对象生效,直到;

记住library(gridExtra) library(ggExtra) library(cowplot) # generate some data df_hm = cbind( expand.grid( rows = sample(letters, 10), cols = sample(LETTERS, 10) ), value = rnorm(100) ) # plot the heatmap gg_hm = df_hm %>% ggplot(aes(x = rows, y = cols, fill = value)) + geom_tile() + theme(legend.position = "bottom") gg_rows = df_hm %>% group_by(rows) %>% summarize(value = mean(value)) %>% ggplot(aes(x = rows,y = value)) + geom_bar(stat = "identity", position = "dodge") gg_cols = df_hm %>% group_by(cols) %>% summarize(value = mean(value)) %>% ggplot(aes(x = cols, y = value))+ geom_bar(stat = "identity", position = "dodge") + coord_flip() gg_empty = df_hm %>% ggplot(aes(x = cols, y = value)) + geom_blank() + theme(axis.text = element_blank(), axis.title = element_blank(), line = element_blank(), panel.background = element_blank()) # try this with grid.arrange grid.arrange(gg_rows, gg_empty, gg_hm, gg_cols, ncol = 2, nrow = 2, widths = c(3, 1), heights = c(1, 3)) 是C ++最强大的功能之一。

答案 1 :(得分:5)

double d = GetClass(0)->GetDouble();内存泄漏。你new了解函数中的对象,然后返回它。您使用返回的对象来调用成员函数,然后丢弃表达式末尾的指针。由于您不再拥有指针,因此您可以更长时间地调用删除并释放您抓取的内存。

请记住,对new / new[]的每次通话都需要拨打delete / delete[]

的匹配电话

既然我们有智能指针,我们可以使用std::unique_ptr解决这个问题。指针将为您管理内存,一旦超出范围,它将删除指针。

答案 2 :(得分:3)

实际上,您实例化一个对象,但不存储指向它的指针,这已经是内存泄漏。无论何时使用new分配对象,作为程序员,您都有责任确保相应地删除该对象。

您的后一个示例正常运行。使用std::unique_ptr可以省去这种担心,因为它会在销毁时自动删除其指向的对象。

答案 3 :(得分:2)

是的,您仍然需要delete

GetClassDerivedADerivedB动态分配存储空间。无论您是否将结果指针存储在任何位置,如果内存未被删除,内存将会泄漏。

如您所知,std::unique_ptr<Base>解决了您的问题。

double d = GetClass(0)->GetDouble();

如果GetClass返回std::unique_ptr,那么它将在包含它的完整表达式的末尾被破坏,这将删除指针。

答案 4 :(得分:2)

如果你new必须 delete(当然很少有例外情况,例如你在程序关机期间故意泄漏对象以加快速度并且你知道析构函数没有任何用处 - 但这是一个边缘情况)。就那么简单。如果将new的返回值分配给变量并不重要 - 仍然分配内存并需要释放。如果你没有跟踪返回的指针以便稍后将其删除,那么它就会被泄露。

使用std::unique_ptr可以帮助您获取指针的所有权,并在unique_ptr超出范围时释放它。