实现对映射进行迭代的类迭代器
implementing class iterator that iterates over a map
如何创建一个类迭代器,在不导致内存泄漏的情况下对通用映射节点进行迭代?我的映射有一个名为"pair"的类,它是泛型的,有一个值和一个键。还有一个名为node的类,它包含一对指向下一个节点和前一个节点的指针。映射本身包含头节点。以及地图大小。。这个代码工作正常,我的问题是它有内存泄漏。因为迭代器是一个类(我们被要求实现为一个类,而不仅仅是一个节点),并且它包含一个指向具有对的node的指针。我们不能通过删除节点来删除对,只要我们想使用迭代器析构函数cause来完全删除对和导致映射中元素丢失的节点。你能给我一些建议吗?如何在没有内存泄漏的情况下正确实现?非常重要的是: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){}
您需要使用一个准确反映目录结构的相对路径。示例:
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
# ...
基本上,你会想在你"包括"的每个子目录中创建一个"Makefile",它定义了在这些子目录中构建每个目标的规则(并使用规则中相对于根Makefile目录的路径),在你的顶级Makefile中,类似地,您将通过它们相对于顶级Makefile目录的路径(而不是文件名)来引用这些文件/目标。
给定的目录布局
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命令的开头包含空格必须用选项卡替换才能实现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 )
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- 使用一个迭代器迭代向量的向量
- 使用给定的第一个和最后一个迭代器迭代范围
- C++ std::list<T>::迭代器 迭代器是否具有<T>对成员函数的访问?
- 无法使用迭代器迭代数组类型的 GVariant
- 自定义迭代器包装另一个迭代器:迭代到底层的end迭代器而不进行检查
- 为什么在c++ 11中所有的迭代器/迭代器适配器都不能移动?