set :: insert是保存副本还是指针C++

SIM*_*MEL 3 c++ set stdset

函数是否set::insert保存指向元素或其副本的指针.意思是,我可以执行以下代码,还是必须确保指针不被删除?

int *a;
*a=new int(1);
set<int> _set;
_set.insert (*a);
delete a;
*a=new int(2);
_set.insert (*a);
delete a;
Run Code Online (Sandbox Code Playgroud)

我给出了示例int,但我的真实程序使用了我创建的类.

phl*_*psy 13

所有STL容器都存储插入数据的副本.看看这里的部分"说明"中的第三段:容器(和std::set车型容器)拥有自己的元素.有关详细信息,请参阅以下脚注[1].特别是对于std::set这里下的部分"类型的要求".在Key必须可以分配.

除此之外,您可以轻松测试:

struct tester {
  tester(int value) : value(value) { }
  tester(const tester& t) : value(t.value) {
    std::cout << "Copy construction!" << std::endl;
  }
  int value;
};

// In order to use tester with a set:
bool operator < (const tester& t, const tester& t2) {
  return t.value < t2.value;
}

int main() {
    tester t(2);

    std::vector<tester> v;
    v.push_back(t);

    std::set<tester> s;
    s.insert(t);
}
Run Code Online (Sandbox Code Playgroud)

你会永远看到Copy construction!.

如果你真的想存储类似对象的引用,你可以存储指向这些对象的指针:

tester* t = new tester(10);
{
    std::set<tester*> s;
    s.insert(t);
    // do something awesome with s
} // here s goes out of scope just as well the contained objects
  // i.e. the *pointers* to tester objects. The referenced objects
  // still exist and thus we must delete them at the end of the day:
delete t;
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,您必须正确地删除对象,这有时非常困难.例如,异常可以显着改变执行路径,而您永远不会达到正确的程度delete.

或者你可以使用智能指针,如boost::shared_ptr:

{
    std::set< boost::shared_ptr<tester> > s;
    s.insert(boost::shared_ptr<tester>(new tester(20)));
    // do something awesome with your set
} // here s goes out of scope and destructs all its contents,
  // i.e. the smart_ptr<tester> objects. But this doesn't mean
  // the referenced objects will be deleted.
Run Code Online (Sandbox Code Playgroud)

现在智能指针会照顾你并在适当的时候删除它们引用的对象.如果您复制了其中一个插入的智能指针并将其转移到其他位置,则在引用此对象的最后一个智能指针超出范围之前,不会删除通常引用的对象.

哦顺便说一句:永远不要std::auto_ptr在标准容器中使用s作为元素.它们奇怪的复制语义与容器存储和管理数据的方式以及标准算法如何操纵它们的方式不兼容.我确信StackOverflow上有很多关于这个不稳定问题的问题.