我有一个类Bar
,它的成员类型为Foo
。类Foo
应该仅以某些固定和恒定状态构造,这些状态基于Tag
进行区分。由于我不希望在任何其他状态下构造Foo
,因此我将其构造函数设为私有,并实现了工厂FooFactory
。
在Bar
的构造函数的初始化程序列表中,我调用函数make_Foo
,该函数根据Foo
返回Tag
的正确实例。
#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;
}
我希望在用Foo
构造Tag::C
时抛出一个异常,但未实现。上面的代码引发了此异常,但是Valgrind Memcheck表示在这种情况下存在内存泄漏。
在进一步调查中,我发现即使bar.foo
并非由工厂创建的,Tag::C
仍通过未知的bar.foo
和空Tag
。这是在这种情况下泄漏的内存吗?抛出异常时,如何避免这种情况发生?
ps。实际上,std::string
是非类型的模板类,对于Foo
,使用另一个模板参数。这就是为什么我需要标签分派。
答案 0 :(得分:2)
由于程序过早终止,可能会出现“内存泄漏”。为了执行所有析构函数并释放内存,您必须不允许异常逸出main
函数(或调用std::abort
或引发终端信号)。
具有静态持续时间的对象在主返回后被销毁,并且如果终止进程,则不会清除静态对象。此类静态对象可能已分配了动态内存,如果静态对象未被破坏,则动态内存可能会泄漏。即使您不这样做,标准库也可能使用带有静态存储的对象。例如,std::cout
对象。