我有一个Base
类,有两个派生类DerivedA
和DerivedB
以及一个返回指针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");
}
DerivedA
和DerivedB
都实现了一个方法,比如说GetDouble()
,这个方法是我唯一感兴趣的是构建这些类中的任何一个:
double d = GetClass(0)->GetDouble();
我的问题是:当我调用GetClass(0)时,我创建了一个应该被删除的指针。但是,我没有将它实例化为一个对象。我还需要删除它吗?
类似的东西:
Base* c = GetClass(0);
double d = c->GetDouble();
delete c;
如何使用std::unique_ptr
?
提前谢谢。
答案 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
。
GetClass
为DerivedA
或DerivedB
动态分配存储空间。无论您是否将结果指针存储在任何位置,如果内存未被删除,内存将会泄漏。
如您所知,std::unique_ptr<Base>
解决了您的问题。
double d = GetClass(0)->GetDouble();
如果GetClass
返回std::unique_ptr
,那么它将在包含它的完整表达式的末尾被破坏,这将删除指针。
答案 4 :(得分:2)
如果你new
你必须 delete
(当然很少有例外情况,例如你在程序关机期间故意泄漏对象以加快速度并且你知道析构函数没有任何用处 - 但这是一个边缘情况)。就那么简单。如果将new
的返回值分配给变量并不重要 - 仍然分配内存并需要释放。如果你没有跟踪返回的指针以便稍后将其删除,那么它就会被泄露。
使用std::unique_ptr
可以帮助您获取指针的所有权,并在unique_ptr
超出范围时释放它。