【问题标题】:C++ dynamic allocationC++ 动态分配
【发布时间】:2013-06-18 11:24:01
【问题描述】:

我对以下说明感到非常困惑:

#include <iostream>
#define MAX_IT 100
using namespace std;

class Integer{

private :
    int a;
public:
    Integer(int valoare){a=valoare;}
    int getA(){return a;}
    void setA(int valoare){a=valoare;}
};

int main(){
    Integer* a=new Integer(0);

    //cout<<a[0].getA();
    for(int i=1;i<=MAX_IT;i++)
    {
        a[i]=*(new Integer(i));
    }

    for(int i=0;i<=MAX_IT;i++)
        cout<<a[i].getA()<<endl;

    return 13;
}

它适用于 MAX_IT 的小值,但是当我尝试将 MAX_IT 设置为 1000 时,它不再起作用。 最初,我认为“新”运算符应该完成这项工作,但在阅读了一些文档后,我明白它根本不应该像这样工作(超出范围的数组)。

所以我的问题是:为什么它适用于较小的 MAX_IT 值而不适用于较大的值?

编辑:

我正在为一个更大的程序试验这段代码,但不允许我使用 STL。你没有理解我的担心:如果我有 Integer *var=new Integer[10]; for(int k=1;K

【问题讨论】:

  • 如果你能帮上忙,千万不要使用new
  • 恐怕在 C++ 标准中没有任何东西可以使它适用于小型 MAX_IT,但不适用于大型。 a 很小的时候很可能在内存中没有任何东西,但这主要取决于您的编译器。只需编写正确的代码;)
  • ? return 13; ?????认真的吗?
  • @milleniumbug:运行那个程序会带来厄运!

标签: c++ arrays dynamic


【解决方案1】:

因为通过为一个 Integer 分配空间,然后将其用作多个Integers 的数组,您的代码会调用未定义的行为, strong> 意味着它可以做任何事情,包括崩溃、看似正常的工作或将恶魔从你的鼻子里拉出来。


不管怎样,它正在泄漏内存。如果您不需要动态内存分配,请不要使用它。

a[i]=*(new Integer(i));

还有kaboom,你丢失了指向Integer 的指针,以后没有机会delete 它。泄漏。


如果您不需要原始数组,请不要使用它们。首选std::vector。如果 C++ 太难,或者切换到 C。

std::vector<Integer> vec;
vec.push_back(Integer(1337));

【讨论】:

  • @milleniumbug 哈哈。只是我很惊讶能得到如此简单的回答,而other answers of mine 更有用,更不受欢迎(甚至是双重投票)。有时我只是不明白 SO 社区的逻辑...... :(
  • 哈,猜猜谁给了你一个很好的答案一个开明的。不错的逆向心理学策略。
  • @Radu Not allowed? 作业还是笨老板还是嵌入式平台?
  • @Radu 如果我被允许使用 C++ 而不允许使用 STL,我会自己重写 STL 的所需部分;)因为我可以。
  • @milleniumbug 好吧,再想一想,如果不允许我使用 STL,我只会使用 C++ 标准库。
【解决方案2】:

当你稍微溢出缓冲区时,事情往往会很好地工作的原因是...... 内存碎片!谁会猜到?

为避免内存碎片,分配器不会只返回sizeof (Integer) 的块。他们会给你一个更大的块,以确保如果该块在相邻块之前被释放,它至少足够大以供使用。

具体有多大可能因架构、操作系统、编译器版本甚至机器中物理内存的大小而异。你应该认为它是完全不可预测的。此外,一些旨在帮助捕获此类错误的库会强制将任何小对象放在块的末尾而不是开头,因此额外的字节可能是负数组索引而不是正数。

因此,永远不要指望在对象之后(或之前)免费为您提供空闲空间。


大师注:偶尔有人想出一个有效使用额外内存的方法,asks for a way to discover how large it is。一个很好的例子是std::vector 的容量(不是大小!)可以调整以匹配实际分配的空间而不是请求的空间,因此减少(平均)所需的重新分配次数。此类请求通常与其他 guru 分配器 API 配对使用,例如,如果碰巧相邻有空闲块,则能够就地扩展分配。


请注意,在您的特定情况下,您仍然有未定义的行为,因为您在尚未首先构造的非 POD 对象上调用 operator=。如果你给class Integer 一个微不足道的默认构造函数,它会改变。

【讨论】:

  • 感谢您的回答,非常感谢!
【解决方案3】:

你确实需要

Integer* a=new Integer[MAX_IT];

//cout<<a[0].getA();
for(int i=1;i<MAX_IT;i++) << note < not <=
{
    a[i]=i;
}

最好还是使用 std::vector

【讨论】:

  • 我正在为一个更大的程序试验这段代码,但不允许我使用 STL。你没有理解我的担心:如果我有 Integer *var=new Integer[10]; for(int k=1;K
  • 您的代码错误;任何事情都可能发生。在你的情况下,它有时会起作用,但有时却不起作用。修复你的代码,一切都会好起来的
猜你喜欢
  • 2020-12-05
  • 1970-01-01
  • 2021-02-12
  • 2015-12-07
  • 2010-12-31
  • 2015-06-27
  • 2021-02-28
  • 2012-01-20
  • 1970-01-01
相关资源
最近更新 更多