[英]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.