C++ 使用自引用元素交换容器
当容器包含具有指向容器本身的指针的元素时,通过指针交换进行交换的标准版本不起作用,交换也不会检查任何这种可能性。 有没有办法告诉容器标准交换不起作用,并使用不同的版本? 实施此类互换的最佳方式是什么 下面的示例解释了该问题C++ 使用自引用元素交换容器,c++,C++,当容器包含具有指向容器本身的指针的元素时,通过指针交换进行交换的标准版本不起作用,交换也不会检查任何这种可能性。 有没有办法告诉容器标准交换不起作用,并使用不同的版本? 实施此类互换的最佳方式是什么 下面的示例解释了该问题 template<template<typename T,typename = std::allocator<T> > class H> struct kid { typedef H<kid> home_type;
template<template<typename T,typename = std::allocator<T> > class H>
struct kid
{
typedef H<kid> home_type;
typedef int id_t;
kid(const home_type& home,int m,typename home_type::size_type c=-1)
: home_(&home)
, me_(m)
, idx_(c)
{
}
id_t me()const
{
return me_;
}
id_t cousin()const
{
return (*home_).size() < idx_ ? -1 : (*home_)[idx_].me();
}
private://default copy & assign ok???
const home_type* home_;
typename home_type::size_type idx_;
id_t me_;
};
int main()
{
typedef kid<std::vector> kid_t;
typedef std::vector<kid_t> home_t;
home_t home1,home2;//two neighbors
home1.push_back(kid_t(home1,1));//elderly kid
home1.push_back(kid_t(home1,2,0));//the cousins
home1.push_back(kid_t(home1,3,0));
home1.push_back(kid_t(home1,4,0));
home2.push_back(kid_t(home2,10));//first kid
home2.push_back(kid_t(home2,20));//second kid
home2.push_back(kid_t(home2,30,0));//cousin of first kid.
home2.push_back(kid_t(home2,40,1));//cousin of second kid
for(home_t::const_iterator it = home1.begin(); it!= home1.end(); ++it)
{
std::cout<<(*it).me()<<" "<<(*it).cousin()<<"\n";
}
std::cout<<"\n";
for(home_t::const_iterator it = home2.begin(); it!= home2.end(); ++it)
{
std::cout<<(*it).me()<<" "<<(*it).cousin()<<"\n";
}
std::cout<<"\nexchange home\n";
std::swap(home1,home2);//they exchanged their house, surely this doesn't work.
//what is the best way to do this?
for(home_t::const_iterator it = home1.begin(); it!= home1.end(); ++it)
{
std::cout<<(*it).me()<<" "<<(*it).cousin()<<"\n";
}
std::cout<<"\n";
for(home_t::const_iterator it = home2.begin(); it!= home2.end(); ++it)
{
std::cout<<(*it).me()<<" "<<(*it).cousin()<<"\n";
}
//all the kids got confused, they points to neighborhood kids as their cousins
}
模板
结构孩子
{
类型def H home_类型;
typedef int id_t;
kid(常量home_type&home,int m,typename home_type::size_type c=-1)
:主页\主页(&home)
,我(m)
,idx_3;(c)
{
}
id\u t me()常量
{
把钱还给我;
}
id\u t表亲()常量
{
return(*home..size() std::cout您可以为您的类型实现std::swap:
void std::swap(std::vector<kid_t> &first,std::vector<kid_t> &second)
{
//here is your implementation or three lines of default swap
}
void std::swap(std::vector&first,std::vector&second)
{
//这是您的实现或三行默认交换
}
您可以为您的类型实现std::swap:
void std::swap(std::vector<kid_t> &first,std::vector<kid_t> &second)
{
//here is your implementation or three lines of default swap
}
void std::swap(std::vector&first,std::vector&second)
{
//这是您的实现或三行默认交换
}
我看不到任何使用swap
的方法。我能想到的唯一方法是在kid
中提供一个move
函数,将孩子从一个家移动到另一个家。然后编写自己的函数来移动孩子。我看不到任何使用swap
的方法。我能想到的唯一方法是of在kid
中提供了一个move
函数,可以将孩子从一个家移动到另一个家。然后编写自己的函数来移动孩子。这里的问题似乎更多的是设计问题,而不是交换问题
你(基本上)使用一个指向一个变量的指针,你没有将自己指定为孩子的标识符……因此,当然,只要孩子们四处走动,它就会断开。(实际上,它比指针稍微好一点,但不会太多)
您有两种解决方案:
- 基本>自己实例化它们
- 更复杂的>工厂+id
当然,你也有一个问题,那就是你捆绑了Home
及其实现……但是我让你自己编写一个合适的Home
类。顺便说一句,由于STL容器的模板参数数量既取决于容器,也取决于你正在使用的STL的实际实现,所以你的解决方案是远没有使用真正的类那么通用;)
基本:
class kid
{
public:
kid(kid* related = 0): m_related(related) {}
// methods
private:
// other attributes
kid* m_related;
};
int main(int argc, char* argv[])
{
Home home1, home2;
kid* kid1 = home1.insert(new kid(home1, 1));
home1.insert(new kid(home1, 2, kid1));
kid* kid2 = home2.insert(new kid(home2, 1));
kid* kid3 = home2.insert(new kid(home2, 2));
home.insert(new kid(home2, 3, kid2));
home.insert(new kid(home2, 4, kid3));
swap(home1,home2); // just swapping the vectors, since it only moves pointers not the objects
}
这是最简单的方法,但我当然还是诅咒你,因为我有两个孩子的id是1
工厂
class KidFactory;
class KidKey { friend class KidFactory; KidKey() {} };
class Kid
{
public:
Kid(KidKey, Id id, Id cousinId);
Id getId() const { return m_id; }
const Home* getHome() const;
void setHome(const Home& home);
private:
const Home* m_home;
Id m_id;
Id m_cousinId;
};
// Factory
class KidFactory
{
public:
Kid& createKid(Id cousinId = -1)
{
m_kids.push_back(Kid(KidKey(), m_kids.size(), cousinId));
return m_kids.back();
}
Kid& getKid(Id id)
{
return m_kids.at(id); // notice that might generate out_of_range exception
}
private:
std::vector<Kid> m_kids;
};
class Home
{
public:
void insert(Kid& kid)
{
m_kids.push_back(kid.getId());
kid.setHome(*this);
}
};
int main(int argc, char* argv[])
{
KidFactory factory;
Home home1, home2;
home1.insert(factory.createKid());
home1.insert(factory.createKid(home1.front().getId()));
Kid& kid1 = factory.createKid();
home2.insert(kid1);
home2.insert(factory.createKid(kid1.getId()));
// once again swapping vectors is fine
}
class工厂;
类KidKey{friend类KidFactory;KidKey(){};
班童
{
公众:
孩子(孩子,身份证,表亲);
Id getId()常量{return m_Id;}
常量Home*getHome()常量;
无效设置原点(常量原点和原点);
私人:
康斯特之家*m_之家;
Id m_Id;
我是堂兄弟;
};
//工厂
基德级工厂
{
公众:
Kid&createKid(Id cousinId=-1)
{
m_kids.push_back(Kid(KidKey(),m_kids.size(),cousinId));
返回m_kids.back();
}
Kid&getKid(Id)
{
返回m_kids.at(id);//注意,可能会生成超出范围的异常
}
私人:
性病::向量m_儿童;
};
班级之家
{
公众:
无效插入(基德和基德)
{
m_kids.push_back(kid.getId());
kid.setHome(*这个);
}
};
int main(int argc,char*argv[])
{
基德工厂;
Home Home 1、Home Home 2;
home1.insert(factory.createKid());
home1.insert(factory.createKid(home1.front().getId());
Kid&kid1=factory.createKid();
home2.插入(kid1);
home2.insert(factory.createKid(kid1.getId());
//再次交换向量是好的
}
适当的设计导致代码容易编写……但C++中有一些模板:(
< P>)这里的问题似乎比交换问题更像设计问题。
你(基本上)使用一个指向一个变量的指针,你没有将自己指定为孩子的标识符……因此,当然,只要孩子们四处走动,它就会断开。(实际上,它比指针稍微好一点,但不会太多)
您有两种解决方案:
- 基本>自己实例化它们
- 更复杂的>工厂+id
当然,你也有一个问题,那就是你捆绑了Home
及其实现……但是我让你自己编写一个合适的Home
类。顺便说一句,由于STL容器的模板参数数量既取决于容器,也取决于你正在使用的STL的实际实现,所以你的解决方案是远没有使用真正的类那么通用;)
基本:
class kid
{
public:
kid(kid* related = 0): m_related(related) {}
// methods
private:
// other attributes
kid* m_related;
};
int main(int argc, char* argv[])
{
Home home1, home2;
kid* kid1 = home1.insert(new kid(home1, 1));
home1.insert(new kid(home1, 2, kid1));
kid* kid2 = home2.insert(new kid(home2, 1));
kid* kid3 = home2.insert(new kid(home2, 2));
home.insert(new kid(home2, 3, kid2));
home.insert(new kid(home2, 4, kid3));
swap(home1,home2); // just swapping the vectors, since it only moves pointers not the objects
}
这是最简单的方法,但我当然还是诅咒你,因为我有两个孩子的id是1
工厂
class KidFactory;
class KidKey { friend class KidFactory; KidKey() {} };
class Kid
{
public:
Kid(KidKey, Id id, Id cousinId);
Id getId() const { return m_id; }
const Home* getHome() const;
void setHome(const Home& home);
private:
const Home* m_home;
Id m_id;
Id m_cousinId;
};
// Factory
class KidFactory
{
public:
Kid& createKid(Id cousinId = -1)
{
m_kids.push_back(Kid(KidKey(), m_kids.size(), cousinId));
return m_kids.back();
}
Kid& getKid(Id id)
{
return m_kids.at(id); // notice that might generate out_of_range exception
}
private:
std::vector<Kid> m_kids;
};
class Home
{
public:
void insert(Kid& kid)
{
m_kids.push_back(kid.getId());
kid.setHome(*this);
}
};
int main(int argc, char* argv[])
{
KidFactory factory;
Home home1, home2;
home1.insert(factory.createKid());
home1.insert(factory.createKid(home1.front().getId()));
Kid& kid1 = factory.createKid();
home2.insert(kid1);
home2.insert(factory.createKid(kid1.getId()));
// once again swapping vectors is fine
}
class工厂;
类KidKey{friend类KidFactory;KidKey(){};
班童
{
公众:
孩子(孩子,身份证,表亲);
Id getId()常量{return m_Id;}
常量Home*getHome()常量;
无效设置原点(常量原点和原点);
私人:
康斯特之家*m_之家;
Id m_Id;
我是堂兄弟;
};
//因素