2016-01-16 79 views
1

我对以下测试片段有所怀疑。我使用节点指针指向函数test2返回的节点实例。为什么删除失败?C++中的内存管理错误

任何意见,将不胜感激。谢谢!

struct Node 
{ 
    int a; 
}; 
Node& test2(Node &n) 
{ 
    Node *p = new Node; 
    p->a = n.a + 5; 
    return *p; 
} 
Node* test3(Node &n) 
{ 
    Node *p = new Node; 
    p->a = n.a + 5; 
    return p; 
} 
int main() 
{ 
    Node m; 
    m.a = 12; 
    Node n = test2(m); 
    Node *x = test3(n); 
    cout << m.a << ";" << n.a << ";" << x->a << endl; 
    delete x; //OK 
    x = &n; 
    delete x; //Error 
    return 0; 
} 

回答

2

当你写

Node n = test2(m); 

n不是由test2创建的Node参考。它是一个拷贝它。由test2创建的Node被泄露。你需要:

Node& n = test2(m); 

另外:我假设这是一个练习来理解参考和指针。对于一个真正的计划,你总是想写:

std::unique_ptr<Node> test4(const Node& n) 
{ 
    std::unique_ptr<Node> result{new Node}; 
    result->a = n.a + 5; 
    return result; 
} 

甚至更​​好:

std::unique_ptr<Node> test4(const Node& n) 
{ 
    auto result = std::make_unique<Node>(); 
    result->a = n.a + 5; 
    return result; 
} 

无论使用哪种解决方案,您无需理会删除分配Node - 中当调用代码中的unique_ptr超出范围时,编译器会为您执行此操作。

+0

非常感谢! –

+0

下来的选民照顾解释为什么? (如果可能,我想改进答案)。 –

+0

我想提出您的评论。但我不知道为什么当我点击向上箭头时数字会变成负数... –

1

test2返回被复制(或移动)到n的对象Node的引用,因为n不是引用。 此对象现在驻留在堆栈上,因此堆栈上的对象调用delete是非法的。

+0

@Downvoter请解释。 –

+0

谢谢你的帮助! –

+0

有一个upvote补偿。 –

1

为什么删除失败?

这里

x = &n; 
delete x; //Error 

你分配一个局部变量

Node n = test2(m); 

不能(也不需要)被delete处理的地址。

+0

谢谢你的解释! –