簡體   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