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返回一些退出代码,以指示出现了问题?
为什么不只是让内存“泄漏”?你的程序被终止了,那你为什么要关心内存呢?我不知道怎么处理这个问题。也许我真的不应该关心。我开始担心这个问题,因为我在集群上运行我的程序,在没有正确清理所有内存的情况下会生成核心转储文件。我没有考虑静态对象.这确实可能是问题所在!