C++在这里发生了什么

Dan*_*iel 0 c++ memory-management new-operator

假设我有一个包含Records的类TwoWayList,而GetRec实际上在堆上创建了一个新列表,这里是方法

void GetRec(TwoWayList<Record> &rec)
{
   TwoWayList<Record>* list= new TwoWayList<Record>();
   Record r;
   list->Insert(&r);
}
Run Code Online (Sandbox Code Playgroud)

现在我有以下两个场景,第一个在我调用delete时死亡,另一个我只是得到一个空的引用记录,所以当我调用MoveToStart()我得到一个段错误,但是如果我只是删除它工作. ..

int main () {
    TwoWayList<Record> record;
    GetRec(record);
    record.MoveToStart();
    delete &record;//crash
   return 0;
}

int main () {
    TwoWayList<Record> *record;
    GetRec(*record);
    record->MoveToStart(); //segfault
    delete record;
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

那么最近怎么样?我在方法的堆中创建一个TwoWayList,因此我不能删除(事实上,如果我不删除它不会是泄漏吗?)是什么方法从这里的方法获取TwoWayList以便我以后可以删除吗?

谢谢

丹尼尔

Tim*_*Tim 5

你的第一个main在堆栈上创建记录 - 而不是堆.所以你对delete堆栈变量地址的尝试崩溃了.

你的第二个main永远不会分配record.因此,当您尝试使用指针时,会出现段错误.

此外,您的函数分配内存,但然后忘记它并泄漏它.我的意思是你创建一个新的list,但永远不要抓住指针.一旦函数退出,您就不再有指向您创建的列表的指针 - 可能不是您想要做的.

GetRec 也忽略了输入参数 - 也可能不是你想要的.

猜猜你在尝试什么......

void GetRec(TwoWayList<Record> &rec)
{
    Record r;
    rec.Insert(r);
}

int main () {
    TwoWayList<Record> record;
    GetRec(record);
    record.MoveToStart();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将创建一个TwoWayList(命名记录),将对记录的引用传递给函数GetRec.GetRec创建一个Record并将其插入TwoWayList.回来main,它在记录上调用MoveToStart(现在有一个Record插入其中).

这可以避免使用堆栈进行new/delete的任何问题,当您将其插入TwoWayList时,以成本复制Record.令人怀疑的是,该副本的性能成本对您来说很重要.但如果确实如此,那就这么说吧.