在C ++中找出值语义

时间:2014-12-09 06:55:12

标签: c++ memory-leaks

我有一个包含以下成员的类String:

Class String{
    ...
    private:

    char* word

    int length
}

String的复制赋值返回String&并在堆上分配单词。

我还有一个用C编写的链表类,它有一个函数:

void *popFront(struct List *list)
{
    struct Node prevHead = list->head
    list->head = prevHead->next;
    void *info = prevHead->info;
    free(prevHead);
    return info;
}

我的任务是为使用C函数的C ++链表编写相同的函数。这就是我所拥有的:

String List::popFront()
{
    String s = (*(String *) ::popFront(&list));//casting the void * to String
    return s;

}

C ++方法应该按值返回对象。这就是我认为该方法会做的事情。然而, 我得到了内存泄漏。有关如何修改List :: popFront()以便按值返回的任何提示?感谢。

3 个答案:

答案 0 :(得分:1)

首先将返回的指针本地存储为指向字符串的指针,然后创建字符串的本地副本,然后删除对象,指针指向并最终返回本地副本。

编辑: 顺便说一句。您可以使用c ++ 11的智能指针来避免额外的副本:

String List::popFront()
{
    auto s = std::unique_ptr<String>((String*) ::popFront(&list));  
    return *s;
}

但这可能不是,老师的目标。

答案 1 :(得分:0)

您声明String List::popFront(),它返回一个对象,而不是一个指针。 String s = ...声明一个对象,而不是指针或引用。因此,为s构建新对象s作为::popFront返回的副本,然后是下一个返回s的{​​/ em>,并且s本身会被销毁。但是,由::popFront()取消链接的对象仍然在堆上,从而导致泄漏。

不要创建String对象的中间副本,将指针返回到未链接的对象,以便调用者可以在使用后将其链接到自己的列表或delete

String *List::popFront()
{
    String *s = (String *) ::popFront(&list);//casting the void * to String *
    return s;
}

答案 2 :(得分:0)

popFront从链接列表中删除元素并释放节点,但不释放info部分。这是popFront来电者的责任,例如

String *s = (String *) ::popFront(&list);
delete s;

但是你还必须保留一份副本,你可以从方法

返回
String List::popFront()
{
    String *s = (String *) ::popFront(&list);
    String tmp = *s;
    delete s;
    return tmp;
}