3

函数是否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;

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

4

4 回答 4

14

所有 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);
}

你总会看到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;

但在这种情况下,您必须注意正确删除对象,这有时非常困难。例如,异常可以显着改变执行路径,而您永远无法到达正确的位置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.

现在智能指针会照顾你并在正确的时间删除它们引用的对象。如果您复制了其中一个插入的智能指针并将其转移到其他地方,则通常引用的对象将不会被删除,直到引用该对象的最后一个智能指针超出范围。

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

于 2011-02-25T21:46:07.027 回答
1

std::set将复制您插入的元素。

于 2011-02-25T21:39:05.117 回答
0

您正在将指针保存到集合中。

指针指向的对象不会被复制。
因此,在调用 delete 后,集合中的指针无效。

注意:您可能只想保存整数。

int a(1);
set<int>  s;
s.insert(a); // pushes 1 into the set
s.insert(2); // pushes 2 into the set.

其他几点注意事项:

  • 注意标识符名称开头的下划线。
  • 使用智能指针来保存指针。

指针:

 std::auto_ptr<int>  a(new int(1));
 set<int*>           s;
 s.insert(a.release());

 // Note. Set now holds a RAW pointer that you should delete before the set goes away.
 //       Or convert into a boost::ptr_set<int> so it takes ownership of the pointer.
于 2011-02-25T21:39:52.350 回答
0
int *a;     
*a=new int(1);

此代码是错误的,因为您尝试使用存储在地址处的值a是垃圾。

而且,每个 stl 容器copy元素,除非您使用moveinsert() 和 push_back() 在 C++0x 中获取右值引用的语义。

于 2011-02-25T21:41:28.443 回答