繁体   English   中英

为什么在另一个 ctor 中调用 ctor 时出现问题?

[英]Why there is something wrong when invoking ctor in another ctor?

这是一个演示代码片段( https://godbolt.org/z/31Tq3r ):

 #include<iostream>

class Ctx
{
public:
    enum RUN_MOD
    {
        MOD_RT,
        MOD_NRT,
    };

    Ctx(RUN_MOD runType)
    {
        if(runType == MOD_RT)
        {
            Ctx();
        }
    }

    Ctx()
    {
        m_L = malloc(100);
        std::cout << "set m_L=" << m_L << std::endl;
    }

    void print()
    {
        std::cout <<"print() m_L=" << m_L << std::endl;
    }

private:
    void *m_L;

    const char* const ARG_TYPE_NOT_MATCH = "the type of argument is not match";
    const char* const ARG_NUM_INVALID = "the number of arguments is invalid";
    const char* const STACK_OPS_INPUT_ARG_INVALID = "the input argument passed to the stack ops is invalid";
};


int main()
{
    Ctx ctx(Ctx::RUN_MOD::MOD_RT);

    ctx.print();
}

以下是在 Ubuntu 上调用二进制程序时的输出:

set m_L=0x614c20 
print() m_L=0x400ad0

你看地址不一样。 我确实通过调用 Ctx::Ctx Ctx::Ctx() (由Ctx::Ctx(RUN_MOD runType)调用)来设置m_L 我真的很困惑。

如果您正在寻找一个干净的解决方案,您可以使用 function,默认构造函数应该做什么。 这样你就不需要构造函数委托,这 afaik 不能有条件地应用,你不必弄乱新的放置。

最小的例子:

class Ctx
{
private:
    void DefaultInit()
    {
        m_L = malloc(100);
        std::cout << "set m_L=" << m_L << std::endl;
    } 

public:
    Ctx(RUN_MOD runType)
    {
        if(runType == MOD_RT)
        {
            this->DefaultInit();
        }
    }

    Ctx()
    {
       this->DefaultInit();
    }
}

构造函数委托只能在构造函数的成员初始化列表中使用,不能在构造函数的主体中使用。 这个答案显示了如何通过创建一个公共初始化 function 来完全避免使用构造函数委托,然后多个构造函数可以根据需要调用。

但是,如果您出于某种原因确实想使用构造函数委托,那么在这种情况下, Ctx()构造函数应该委托给Ctx(RUN_MOD)构造函数,而不是您最初尝试的相反方式,例如:

class Ctx
{
public:
    enum RUN_MOD
    {
        MOD_RT,
        MOD_NRT,
    };

    Ctx(RUN_MOD runType)
    {
        if (runType == MOD_RT)
        {
            m_L = malloc(100);
            std::cout << "set m_L=" << m_L << std::endl;
        }
    }

    Ctx() : Ctx(MOD_RT) // <— here
    {
    }

    void print()
    {
        std::cout << "print() m_L=" << m_L << std::endl;
    }

private:
    void *m_L = nullptr;

    const char* const ARG_TYPE_NOT_MATCH = "the type of argument is not match";
    const char* const ARG_NUM_INVALID = "the number of arguments is invalid";
    const char* const STACK_OPS_INPUT_ARG_INVALID = "the input argument passed to the stack ops is invalid";
};

调用任何 class 的 ctor 会生成它的一个实例,在您发布的代码中,很明显,在Ctx()中分配的m_l不属于由 Ctx (RUN_MOD runType)构造的 object

试试下面的代码

void init_m_l()
{
    m_L = malloc(100);
    std::cout << "set m_L=" << m_L << std::endl;
}

Ctx(RUN_MOD runType)
{
    if(runType == MOD_RT)
       init_m_l();
}

Ctx()
{
    init_m_l();
}

我找到了一个解决方案,这是代码片段( https://coliru.stacked-crooked.com/a/964309f60f62dbd4 ,它有效,但我仍在努力理解它):

#include<iostream>

class Ctx
{
public:
    enum RUN_MOD
    {
        MOD_RT,
        MOD_NRT,
    };

    Ctx(RUN_MOD runType)
    {
        if(runType == MOD_RT)
        {
            new (this)Ctx();
        }
    }

    Ctx()
    {
        m_L = malloc(100);
        std::cout << "set m_L=" << m_L << std::endl;
    }

    void print()
    {
        std::cout <<"print() m_L=" << m_L << std::endl;
    }

    ~Ctx()
    {
        free(m_L);
    }

    Ctx(const Ctx&) = delete;  //to avoid double free

private:
    void *m_L;

    const char* const ARG_TYPE_NOT_MATCH = "the type of argument is not match";
    const char* const ARG_NUM_INVALID = "the number of arguments is invalid";
    const char* const STACK_OPS_INPUT_ARG_INVALID = "the input argument passed to the stack ops is invalid";
};


int main()
{
    Ctx ctx(Ctx::RUN_MOD::MOD_RT);

    ctx.print();
}

这是一个很好的答案,但作者删除了它。 我把它贴在这里让更多人学习。

他的代码:

if(runType == MOD_RT)
{
    Ctx();
}

创建一个临时的 Ctx Ctx() object,然后——就是这样。 不多也不少。 一旦该行代码执行完毕,该临时文件就会被销毁。

There are other major issues with the class, such as using malloc, the class leaks memory due to not following the rule of 3, not initializing all the members (which I addressed by setting m_L to nullptr ), etc.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM