如何创建一个迭代通用映射节点而不会导致内存泄漏的类迭代器? 我的地图上有一个名为" pair"这是通用的,有价值和关键。 也是一个被称为节点的类,它包含一对和指向下一个节点和前一个节点的指针。 地图本身包含头节点。和地图大小.. 这段代码工作,我的问题是它有内存泄漏。 因为迭代器是一个类(我们被要求实现为一个类,而不仅仅是一个节点),它包含一个指向具有一对的Node的指针。每当我们想要使用迭代器析构函数时,我们就不能通过删除节点来删除该对,因为它会完全删除该对和导致元素在地图中丢失的节点。 你能给出一些如何在没有内存泄漏的情况下正确实现的建议吗? 并且非常重要:map函数end()应该返回一个不是map元素之一的随机值(这就是为什么我将它设置为NULL)
template <class KeyType, class ValueType, class CompareFunction = std::less<KeyType> >
class MtmMap {
public:
class Pair {
public:
Pair(const KeyType& key, const ValueType& value)
: first(key), second(value) {}
Pair()
: first(NULL), second(NULL) {}
~Pair(){}
const KeyType first;
ValueType second;
bool operator==(const Pair& pair)const{
if(pair.first==this->first&&pair.second==this->second){
return true;
}
return false;
}
bool operator!=(const Pair& pair)const{
if(this==pair){
return false;
}
return true;
}
Pair& operator=(const Pair& pair){
if(this==&pair){
return *this;
}
this->first=pair.first;
this->second=pair.second;
return *this;
}
Pair& operator=(ValueType val){
this->second=val;
return *this;
}
const KeyType& getFirst(){
KeyType* keyPointer=&first;
return (first);
}
ValueType getSecond(){
ValueType* valPoiner= &second;
return (valPoiner);
}
};
class Node {
public:
Pair* element;
//int plc;
Node* next;
Node* before;
Node() :element(), next(NULL),before(NULL){}
Node(const Node& copyNode) :
element(new Pair(*(copyNode.element))), next(
copyNode.next) ,before(copyNode.before){
}
Node& operator++(){
if(this->next){
return(this->next);
}
Node* node=new Node;
node->next=NULL;
node->element=NULL;
//node->first=NULL;
return(node);
}
Node operator++(int n){
Node result=*this;
++this;
return result;
}
Node& operator--(){
return(this->before);
}
bool operator==(const Node& node)const{
if(node.before==this->before&&node.element==this->element&&node.next==this->next){
return true;
}
return false;
}
bool operator!=(const Node& node)const{
if(this==node){
return false;
}
return true;
}
Node& operator=(const Node& node){
if(this==&node){
return *this;
}
this->before=node.before;
this->element=node.element;
this->next=node.next;
return *this;
}
}
};
class iterator{
public:
Node* p;
iterator():p(){}
iterator(const iterator& it):p(it.p){}
~iterator(){
}
iterator& operator++(){
this->p=this->p->next;
if(this->p){
return *this;
}
this->p=NULL;
return *this;
}
iterator operator++(int n){
iterator result=*this;
++*this;
return result;
}
iterator& operator=(const iterator& it){
if(this==&it){
return *this;
}
this->p=it.p;
return *this;
}
bool operator==(const iterator& iterator)const{
if(this->p==iterator.p){
return true;
}
return false;
}
bool operator!=(const iterator& iterator)const{
if(this->p!=iterator.p){
return true;
}
return false;
}
const Pair& operator*(){
if(*this==end()){
throw MapElementNotFoundException();
}
return *p->element;
}
iterator& begin(){
while(p->before!=NULL){
p--;
}
return *this;
}
iterator& end(){
iterator* it=new iterator();
it->p=NULL;
return *it;
}
};
int mapSize;
Node* head;
iterator iter;
ValueType initializer;
CompareFunction compareFunc;
MtmMap(ValueType val):mapSize(0),head(),iter(),initializer(val){}
答案 0 :(得分:0)
您需要使用准确反映目录结构的相对路径。例如:
include my_set/Makefile
include tests/Makefile
# ...
TEST_OBJS1 = tests/cache_test.o cache.o
TEST_OBJS2 = tests/memcache_test.o memcache.o cache.o user.o
TEST_OBJS3 = my_set/my_set_test.o my_set/my_set.o
# ...
基本上,您要创建一个&#34; Makefile&#34;在每个子目录中,您包括&#34;并定义了构建这些子目录中每个目标的规则(以及使用相对于规则中根Makefile目录的路径),在顶级Makefile中,您将类似地通过其路径引用这些文件/目标相对于顶级Makefile目录(而不是文件名)。
答案 1 :(得分:0)
给出目录布局:
main/
cache.c
cache.h
memcache.c
memcache.h
user.c
user.h
my_set/
my_set.c
my_set.h
my_set_test.c
tests/
memcache_test.c
cache_test.c
定义宏时,如果只评估一次,请使用:=
而不是=
在为外部可执行文件提供宏名称时,始终提供完整路径
注意:答案在make rule命令的开头包含空格 必须用tab替换才能实现makefile语法
问题无法指定某些头文件的位置,并且无法指示某些.c文件使用哪些头文件。
假设所有未明确位于目录布局中的头文件实际上位于'main /'目录中。
这些显式编译规则是未知的头文件依赖关系具有此文本??? which header files ???
建议的makefile内容如下:
#CC=gcc
CC := /usr/bin/gcc
RM := /usr/bin/rm
# you stated the executables were to be in the main directory
#EXEC1 = /tests/cache_test
#EXEC2 = /tests/memcache_test
#EXEC3 = /my_set/my_set_test
EXEC1 := cache_test
EXEC2 := memcache_test
EXEC3 := my_set_test
# when object in sub directory, include the directory path
TEST_OBJS1 := tests/cache_test.o cache.o
TEST_OBJS2 := tests/memcache_test.o memcache.o cache.o user.o
TEST_OBJS3 := my_set/my_set_test.o my_set/my_set.o
LIBS := -L. -lmtm
DNDEBUG_FLAG := -DNDEBUG
CFLAGS := -Wall -Werror -pedantic-errors -std=c99 -g
# need to tell ''make'' that certain targets do not produce a output file
.PHONY : all clean
# first/default target in makefile
# it has dependencies on each of the 3 executables
# so, by default, the three executables will be generated
all: $(EXEC1) $(EXEC2) $(EXEC3)
@echo "all done"
# link rules needs any 'special' library path and library name parameters
$(EXEC2): $(TEST_OBJS2)
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) $(TEST_OBJS2) -o $@ $(LIBS)
$(EXEC1): $(TEST_OBJS1)
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) $(TEST_OBJS1) -o $@ $(LIBS)
$(EXEC3): $(TEST_OBJS3)
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) $(TEST_OBJS3) -o $@ $(LIBS)
# compile rules have no use for library path and library name parameters
# they do have use for where to find the user supplied header files
# especially if those header files are not in the current directory
# only compile one file in each explicit compile rule
# always place the source file name as the first dependency parameter
# so '$<' can be used to reference it
cache.o: cache.c cache.h list.h set.h
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I.
user.o: user.c user.h set.h list.h
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I.
memcache.o: memcache.c cache.h list.h set.h user.h memcache.h map.h
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I.
my_set/my_set.o: my_set/my_set.c my_set/my_set.h list.h
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I. -Imy_set/.
tests/cache_test.o : tests/cache_test.c ??? which header files ???
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I. -Itests/.
tests/memcache_test.o : tests/memcache_test.c ??? which header files ???
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I. -Itests/.
my_set/my_set_test.o : my_set/my_set_test.c ??? which header files ???
$(CC) $(CFLAGS) $(DNDEBUG_FLAG) -c $< -o $@ -I. -Imy_set/.
# all three directories need to be cleaned
# the ( cd .... && .... ) lines
# start a new sub shell,
# cd to the appropriate directory,
# perform the rm function,
# and exit the sub shell
# which results in being back in the original directory
clean:
$(RM) -f *.o $(EXEC1) $(EXEC2) #(EXEC3)
( cd my_set && $(RM) -f *.o )
( cd tests && $(RM) -f *.o )