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

发布于 2024-10-19 01:50:03 字数 271 浏览 3 评论 0原文

函数 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 给出了示例,但我的实际程序使用我创建的类。

does the function set::insert saves a pointer to the element or a copy of it. meaning, can I do the following code, or I have to make sure that the pointers are not deleted?

int *a;
*a=new int(1);
set<int> _set;
_set.insert (*a);
delete a;
*a=new int(2);
_set.insert (*a);
delete a;

I gave the example with int, but my real program uses classes that I created.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

伤痕我心 2024-10-26 01:50:03

所有 STL 容器都存储插入数据的副本。请参阅此处第三段中的“描述”部分:容器(以及 < code>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);
}

您将始终看到复制构造!

如果您确实想存储诸如对象引用之类的内容,您可以存储指向这些对象的指针:

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;

但在这种情况下,您必须正确删除对象,这有时非常困难。例如,异常可能会极大地改变执行路径,并且您永远无法到达正确的删除

或者您可以使用像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_ptr 作为标准容器中的元素。它们奇怪的复制语义与容器存储和管理数据的方式以及标准算法操作它们的方式不兼容。我确信 StackOverflow 上有很多关于这个不稳定问题的问题。

All STL containers store a copy of the inserted data. Look here in section "Description" in the third paragraph: A Container (and std::set models a Container) owns its elements. And for more details look at the following footnote [1]. In particular for the std::set look here under the section "Type requirements". The Key must be Assignable.

Apart from that you can test this easily:

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

You'll always see Copy construction!.

If you really want to store something like a reference to an object you either can store pointers to these objects:

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;

But in this case you have to take care of deleting the objects correctly and this is sometimes very difficult. For example exceptions can change the path of execution dramatically and you never reach the right delete.

Or you can use smart pointers like 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.

Now the smart pointers takes care for you and delete their referenced objects at the right time. If you copied one of the inserted smart pointers and transfered it somewhere else the commonly referenced object won't be delete until the last smart pointer referencing this object goes out of scope.

Oh and by the way: Never use std::auto_ptrs as elements in the standard containers. Their strange copy semantics aren't compatible with the way the containers are storing and managing their data and how the standard algorithms are manipulating them. I'm sure there are many questions here on StackOverflow concerning this precarious issue.

喵星人汪星人 2024-10-26 01:50:03

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

std::set will copy the element you insert.

吃→可爱长大的 2024-10-26 01:50:03

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

指针所指向的对象不会被复制。
因此,调用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.

You are saving pointers into the set.

The object pointed at by the pointer is not copied.
Thus after calling delete the pointer in the set is invalid.

Note: You probably want to just save integers.

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

Couple of other notes:

  • Be careful with underscores at the beginning of identifier names.
  • Use smart pointers to hold pointers.

Ptr:

 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.
何以畏孤独 2024-10-26 01:50:03
int *a;     
*a=new int(1);

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

而且,每个 stl 都包含 copy 元素,除非您使用带有 insert() 和 push_back() 的 move 语义来获取 C++0x 中的右值引用。

int *a;     
*a=new int(1);

This code is wrong because you try to use the value stored at address a which is a garbage.

And, every stl containers copy elements unless you use move semantics with insert() and push_back() taking rvalue references in C++0x.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文