gpt4 book ai didi

c++ - new 未调用,但已分配内存

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:53:29 27 4
gpt4 key购买 nike

我写了一个简单的Trie执行。这是源代码:

#include <string>
#include <map>

typedef unsigned int uint;

class Trie {
public:
class Node {
public:
Node(const char & _value);
~Node();
char get_value() const;
void set_marker(const uint & _marker);
uint get_marker() const;
bool add_child(Node * _child);
Node * get_child(const char & _value) const;
void clear();
private:
char m_value;
uint m_marker;
std::map<char, Node *> m_children;
};

Trie();
~Trie();
bool insert(const std::string & _str);
bool find(const std::string & _str) const;
private:
Node * m_root;
};
// - implementation (in a different file)
using namespace std;

Trie::Node::Node(const char & _value) :
m_value(_value), m_marker(0), m_children() {
}

Trie::Node::~Node() {
clear();
}

void Trie::Node::clear() {
map<char, Node*>::const_iterator it;
for (it = m_children.begin(); it != m_children.end(); ++it) {
delete it->second;
}
}

void Trie::Node::set_marker(const uint & _marker) {
m_marker = _marker;
}

uint Trie::Node::get_marker() const {
return m_marker;
}

char Trie::Node::get_value() const {
return m_value;
}

Trie::Node * Trie::Node::get_child(const char & _value) const {
map<char, Node*>::const_iterator it;
bool found = false;
for (it = m_children.begin(); it != m_children.end(); ++it) {
if (it->first == _value) {
found = true;
break;
}
}
if (found) {
return it->second;
}
return NULL;
}

bool Trie::Node::add_child(Node * _child) {
if (_child == NULL) {
return false;
}
if (get_child(_child->get_value()) != NULL) {
return false;
}
m_children.insert(pair<char, Node *>(_child->get_value(), _child));
return true;
}

Trie::Trie() :
m_root(new Node('\0')) {
}

Trie::~Trie() {
delete m_root;
}

bool Trie::insert(const string & _str) {
Node * current = m_root;
bool inserted = false;
for (uint i = 0; i < _str.size(); ++i) {
Node * child = current->get_child(_str[i]);
if (child == NULL) {
child = new Node(_str[i]);
current->add_child(child);
inserted = true;
}
current = child;
}
if (current->get_marker() != _str.size()) {
current->set_marker(_str.size());
inserted = true;
}
return inserted;
}

bool Trie::find(const std::string & _str) const {
Node * current = m_root;
bool found = false;
for (uint i = 0; i < _str.size(); ++i) {
Node * child = current->get_child(_str[i]);
if (child == NULL) {
break;
} else {
current = child;
}
}
if (current->get_marker() == _str.size()) {
found = true;
}
return found;
}

这是我的测试程序:

#include <iostream>
#include <sstream>
#include "Trie.h"

int main() {
Trie t;
for (unsigned int i = 0; i < 10000; ++i) {
t.insert("hello");
}
return 0;
}

我的问题是,即使“hello”在第二次尝试插入时已经插入,因此不再调用 new,但仍在分配和取消分配大量内存。当 I 增加 max i 的值时,这个数量会增加。例如,在上面的例子中,valgrind 给出了这个输出:

==10322== HEAP SUMMARY:
==10322== in use at exit: 0 bytes in 0 blocks
==10322== total heap usage: 10,011 allocs, 10,011 frees, 300,576 bytes allocated

我已经确认调用 Node() 构造函数的次数是恒定的。那么为什么以及如何分配和释放所有这些内存?

最佳答案

每次调用 insert 时,都会向其传递一个 const char[6],但它需要一个 const std::string& ,因此每次迭代都会创建一个临时的 std::string,然后将其传递给函数,然后在下一次迭代之前销毁。这澄清了 10000 次分配和取消分配,只剩下 11 次,这大概是您对节点的分配,以及 std::map 内部所做的一切,以及我忽略的其他一些地方(例如字符串或 map 的拷贝)

容器可以分配内存,即使它不包含任何元素,但我认为它应该以其他方式设计,如果容器的任何主要实现做这样的事情,我会感到惊讶。 (尽管双端队列可能是个异常(exception))

关于c++ - new 未调用,但已分配内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14222436/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com