使用operator new分配内存并使用数据初始化

时间:2014-10-24 12:05:27

标签: c++ constructor stack-overflow new-operator initialization-list

在我的项目中,有一百万个输入,我应该将搜索/排序算法与不同数量的输入进行比较,直到一百万个输入。我想用数据一起进行内存分配和初始化,但是我不能实现它。所以我决定这样做;     
    
    

double temp1, temp2, temp3;  //Each line has three numbers
    int i;
    Person *list[N];  //Here, stackoverflow occurs, for example N=500000
    for(i=0; i<N; i++){
        file >> temp1 >> temp2 >> temp3;
        list[i] = new Person(temp1, temp2, temp3);  //I wanted to initialize with data
    }                                          //but if I wrote "new Person[N]" 
                                               //stackoverflow doesn't occur
    
但是有大量的溢出,例如N = 500000。 那么,有没有任何方法将这两者结合起来?(没有溢出和数据初始化)     
    
其次,这两个代码有什么区别;     
    
double temp1, temp2, temp3;  //Each line has three numbers
    int i;
    Person *list[N];  //Here, stackoverflow occurs, for example N=500000
    for(i=0; i<N; i++){
        file >> temp1 >> temp2 >> temp3;
        list[i] = new Person(temp1, temp2, temp3);  //I wanted to initialize with data
    }                                          //but if I wrote "new Person[N]" 
                                               //stackoverflow doesn't occur
    
Person *list[N];
for(i=0; i<N; i++){
    list[i] = new Person();
    }

2 个答案:

答案 0 :(得分:2)

作为初学者,最好避免使用自己的容器。您可以使用标准提供的那些:

...

#include <vector>
#include <cstdlib>  // for EXIT_FAILURE, EXIT_SUCCESS

double temp1, temp2, temp3;  //Each line has three numbers
std::vector<Person> people;
for(int i=0; i<N; i++)
    if (file >> temp1 >> temp2 >> temp3)
        people.emplace_back(temp1, temp2, temp3);
    else
    {
        std::cerr << "error reading 3 numbers from file, terminating\n";
        exit(EXIT_FAILURE);
    }

使用vector(或new Person[n],与new Person*[n]形成对比)将内存中的数据保持在一起(连续)非常有用,因此您的CPU可以获得在您要比较的搜索和排序过程中,从缓存中获得的最大可能收益...如果您的数据难以访问它,则会隐藏被测算法之间性能差异的程度。在堆上分配new Person*[n]和每个Person对象时,数据会分散,访问速度会慢得多。


只是为了解释当前代码发生了什么:

  • 你试图在堆栈上放置太多数据;您可以通过使用单个堆栈托管指针来处理所需数量的动态分配内存(对于应用程序来说,它具有比堆栈空间更大的动态内存,这是正常的。)
  

其次,这两个代码之间是否存在差异;

Person* list[N];                  // first
for(i=0; i<N; i++){
    list[i] = new Person();
}

Person *list = new Person[N];       // second - corrected from "new list[N}"

第一个请求堆栈上的Person*数组,然后将每个指针分配给不同的动态分配的内存地址。充其量,这将使用几乎尽可能多的堆栈内存 - 最糟糕的是大约两倍 - 试图将Person list[N];直接放在堆栈上并且可能以相同的方式失败。它还会在动态内存中散布Person数据,对数据的操作也会不必要地慢。

第二个创建一个动态分配的内存区域,大小足以容纳N Person,并在堆栈上保留一个指针。这不是不合理的(但std::vector仍然是一个更好的主意)。

答案 1 :(得分:0)

在您的示例中,

Person *list[N];

作为堆栈上的局部变量创建。 500,000个指针占用大约2 MB - 这可能会超过某些机器上的堆栈大小。 http://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx

然而,

    //Person *list = new list[N];
    Person **list = new Person* [N];

将在堆上创建您的数组,您应该能够在不耗尽内存的情况下分配它。但是,除了指针数组之外,每个Person对象都有一个大小并需要分配。