在一个数组中,针对每个元素使用std::set

4

我需要针对数组中的每个元素实现 std::set 的功能。我该如何实现这个功能?

我开始使用以下方式在 C++ 中分配动态数组的 std set:

set<int>* entry;

随后是分配:

entry = (set<int>*)malloc(sizeof(set<int>)*32);

没有编译问题,但在访问任何元素时运行时会出现分段错误:
entry[0].insert(23);

非常感谢您的帮助。


3
你还没有创建set本身。 - nhahtdh
4
为什么不使用这个:std::vector<std::set<int>> entries;? - RC.
5个回答

11

那么关于什么?

#include <set>
#include <vector>

int main()
{
        std::vector < std::set<int> > entry(32); // std::vector constructor makes 32 calls to std::set<int> constructor
        entry[0].insert(23);
        // std::vector destructor makes 32 calls to std::set<int> destructor
}

5

在C++中,您使用new来分配内存。与malloc的区别在于构造函数被调用以初始化内存。

entry = new set<int>[32];

4
当你完成使用后,请不要忘记删除它。通常最好使用像 std::vector 这样的容器来管理内存。 - Mike Seymour

4
尽管您已为32个std::set分配了存储空间,但您尚未初始化该内存段(即您的std::set的构造函数尚未被调用),因此您正在尝试在entry[0].insert (23)中操作/访问的内存将导致未定义行为
混合使用C++对象和malloc及其等效物通常(我想写“总是”)被认为是不好的做法。
相反,请转向operator new,它将分配内存并以正确的方式处理对象的构造,还请记住delete已分配的内存以释放内存返回到您的系统(并使对象以真正的方式析构)。

C++中正确的方法

一些答案将包含文本,指出最好使用std::vector<std::set>,但这并不是您问题的答案,因此我会留下这个示例片段

int
main (int argc, char *argv[])
{
  std::set<int> *entries = new std::set<int> [32]; 

  entries[0].insert (123);

  delete [] entries;
}

4
std::vector 真的是一个好的解决方案。如果 insert 抛出异常,你的示例会导致内存泄漏;最简单的修复方法是使用 RAII 包装器来管理数组;而动态数组的这种包装器已经被实现并称为 std::vector - Mike Seymour
@MikeSeymour 这是一个超出问题范围的答案,因此我选择不在我的帖子中包含它。 - Filip Roséen - refp
MikeSeymour是正确的。在C++中,这已经不再是好的实践了。std::array是固定大小数组的另一个选择。 - Neil G

2

这是一个好问题,答案并不显而易见。问题在于每个set对象都希望在使用之前被初始化,而您的代码只为每个set分配了原始内存。以下是修复方法:

#include <vector>
#include <set>

using std::vector;
using std::set;

const int N = 32;

int main() {
    vector< set<int> > entry(N);
    entry[0].insert(23);
    return 0;
}

1
不要尝试在C++类中使用malloc/calloc/realloc等函数,应该使用new。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接