C++ 带有标记分派的const成员构造函数中存在内存泄漏
我有一个类C++ 带有标记分派的const成员构造函数中存在内存泄漏,c++,memory-leaks,constructor,c++14,C++,Memory Leaks,Constructor,C++14,我有一个类Bar,它有一个类型为Foo的成员。类Foo应仅在某些固定和恒定状态下构造,这些状态基于标记进行区分。由于我不希望在任何其他状态下构造Foo,因此我将其构造函数设置为私有,并实现了一个工厂FooFactory 在Bar的构造函数的初始值设定项列表中,我调用函数make_Foo,它根据标记返回Foo的正确实例 #include <stdexcept> #include <string> #include <iostream> enum class T
Bar
,它有一个类型为Foo
的成员。类Foo
应仅在某些固定和恒定状态下构造,这些状态基于标记进行区分。由于我不希望在任何其他状态下构造Foo
,因此我将其构造函数设置为私有,并实现了一个工厂FooFactory
在Bar
的构造函数的初始值设定项列表中,我调用函数make_Foo
,它根据标记返回Foo
的正确实例
#include <stdexcept>
#include <string>
#include <iostream>
enum class Tag
{
A,
B,
C
};
class Foo
{
public:
friend class FooFactory;
const Tag tag;
const std::string string;
private:
Foo(Tag tag, std::string string):
tag {tag}, string {string}
{};
};
class FooFactory
{
public:
static Foo A()
{
return Foo(Tag::A, {"This is string A"});
}
static Foo B()
{
return Foo(Tag::B, {"This is string A"});
}
};
Foo make_Foo(Tag tag)
{
switch(tag)
{
case Tag::A: return FooFactory::A();
case Tag::B: return FooFactory::B();
default: throw std::runtime_error("Called with invalid Tag.");
}
}
class Bar
{
public:
std::string another_string;
const Foo foo;
Bar(Tag tag, std::string another_string):
another_string {another_string}, foo {make_Foo(tag)}
{};
};
int main()
{
Tag tag = Tag::C;
Bar bar(tag, "This is a string");
std::cout << "bar constructed" << std::endl;
}
#包括
#包括
#包括
枚举类标记
{
A.
B
C
};
福班
{
公众:
友邦食品厂;
常量标签;
常量std::字符串;
私人:
Foo(标记,std::string):
标记{tag},字符串{string}
{};
};
食品级工厂
{
公众:
静态fooa()
{
返回Foo(标记::A,{“这是字符串A”});
}
静态foob()
{
返回Foo(标记::B,{“这是字符串A”});
}
};
Foo make_Foo(标签标签)
{
开关(标签)
{
case标记::A:return foodfactory::A();
case标记::B:return foodfactory::B();
默认值:抛出std::runtime_错误(“使用无效标记调用”);
}
}
分类栏
{
公众:
std::string另一个_字符串;
警察富福;
条(标记标签,标准::字符串另一个字符串):
另一个字符串{另一个字符串},foo{make_foo(tag)}
{};
};
int main()
{
Tag=Tag::C;
Bar Bar(标记“这是一个字符串”);
std::cout由于程序过早终止,可能存在“内存泄漏”。为了执行所有析构函数并释放内存,您不得允许异常转义main
函数(或调用std::abort
或引发终端信号)
具有静态持续时间的对象将在主返回后销毁,如果进程终止,则不会进行静态对象清理。如果静态对象未销毁,此类静态对象可能已分配动态内存,而这些动态内存可能会泄漏。即使不销毁,标准库也可能使用具有静态存储的对象。例如std::cout
object.只是一个预感:如果你在Bar
中切换声明顺序,另一个字符串
,和foo
,你仍然会得到内存泄漏吗?如果你正确捕获异常,你仍然会得到泄漏吗?Bar(…):尝试另一个字符串{另一个字符串},foo{make\foo(标记)}{/*ctor code*/}catch{catch code}@Algirdas Preidžius:是的,我在切换订单时也会出现泄漏。@Otto V.是的,或者至少如果我在捕获后重新播放它。我认为异常处理机制应该清理对象(只要不使用new
或delete
)当它们超出范围时?我是否应该在main
中捕获异常,并让main
返回一些退出代码,以表明出现了问题?@JorenV对象的静态持续时间在main返回后被销毁,如果进程终止,静态对象的清理不会发生。这样的静态对象可能会分配动态内存,如果静态对象未销毁,则可能会泄漏。即使不销毁,标准库也可能使用具有静态存储的对象。例如,std::cout
对象。然后我是否应该在main中捕获异常,并让main返回一些退出代码,以指示出现了问题?
为什么不只是让内存“泄漏”?你的程序被终止了,那你为什么要关心内存呢?我不知道怎么处理这个问题。也许我真的不应该关心。我开始担心这个问题,因为我在集群上运行我的程序,在没有正确清理所有内存的情况下会生成核心转储文件。我没有考虑静态对象.这确实可能是问题所在!