【问题标题】:Dynamic memory allocation has undesired output [duplicate]动态内存分配有不需要的输出[重复]
【发布时间】:2014-08-06 13:57:11
【问题描述】:

所以我上周开始学习C++,很自然地,我想熟悉整个指针和面向对象的业务等等。

为此,我正在为一些基本的矩阵计算编写一个非常简单的程序:

# include <iostream>
using std::cout;
using std::cin;

class Matrix {
        int columns; // x
        int rows; // y
        double* matrix;
    public:
        Matrix (int*);
        void printMatrix();
        void free() {
            delete[] matrix;
            return;
            };
};

Matrix::Matrix(int* dim){
    rows = *dim;
    columns = *(dim + 1);
    matrix = new double [columns*rows];
}

void Matrix::printMatrix(){ 
    int i, j;
    for(i = 0; i < columns; i++){
        for(j=0; j < rows; j++){
            cout << matrix[columns*i + j] << " ";
        }
        cout << "\n";
    }
    return;         
}


int* getMatrix ();

int main () {
    Matrix matrix (getMatrix());
    matrix.printMatrix();
    matrix.free();
    return 0;
}

int* getMatrix (){
    int* dim = new int [2];
    cout << "(m x n)-Matrix, m? ";
    cin >> dim[0];
    cout << "n? ";
    cin >> dim[1];
    return dim;
}

当我选择 (4,2) 矩阵时,会出现问题(如我所见)。据我从各种教程中了解到,

matrix = new double [columns*rows];

应该分配这么多内存:columns*rows 乘以 sizeof(double)。此外,每个“单元格”都应使用 0 进行初始化。

但是,选择一个 (4,2) 矩阵,我得到函数 printMatrix() 的以下输出:

0 0 
0 0 
0 6.6727e-319 
0 0 

为什么 (3,2) 条目没有用 0 初始化?

谢谢!

【问题讨论】:

  • @MarkB:这个问题是完全相反的......
  • @Lightness Races in Orbit 接受的答案正好回答了这个问题。
  • @MarkB:嗯,好吧。这并没有使问题相同(根本),但我会保持原样。
  • @JoBe:GetMatrix() 像筛子一样漏水,顺便说一句!
  • @joBe:一旦你有时间进行代码审查。 codereview.stackexchange.com

标签: c++


【解决方案1】:

此外,每个“单元格”都应该用 0 初始化。

不。当您编写 new double[N] 时,语言不会为您做到这一点。

为什么 (3,2) 项没有初始化为 0?

如果你改写new double[N](),它会的!

[C++11: 5.3.4/15]: 创建 T 类型对象的 new-expression 将该对象初始化如下:

  • 如果 new-initializer 被省略,则对象为 default-initialized (8.5);如果不执行初始化,则该对象具有不确定的值。
  • 否则,new-initializer 会根据 8.5 的初始化规则来解释 direct-initialization

当然,这有点模棱两可,因为它似乎在谈论new 的非数组版本,但实际上它意味着两者; Tdouble[4]

实际上,我们可以看到,在数组和非数组情况下,同一部分的措辞都谈到了“对象”,开创了完美的先例:

[C++11: 5.3.4/1]: [..] 如果实体是非数组对象,new-expression 返回一个指向所创建对象的指针。如果是数组,new-expression 返回指向数组初始元素的指针。

现在,证明这条规则基本上是不可能的,因为即使这些值实际上是不确定的,你也可能会遇到不幸并得到全零,但以下代码完全没有令人信服的良好开端:

#include <iostream>
#include <vector>

int main() {
    const std::size_t n = 4;

    {
        std::vector<double> hack;
        hack.push_back(5);
        hack.push_back(6);
        hack.push_back(7);
        hack.push_back(8);
        hack.push_back(9);
        hack.push_back(10);
        hack.push_back(11);
        hack.push_back(12);
    }

    double* a = new double [n];
    double* b = new double [n]();

    for (std::size_t i = 0; i < n; i++)
        std::cout << a[i] << '/' << b[i] << ' ';
    std::cout << '\n';

    delete[] a;
    delete[] b;
}

我设法从中获得了0/0 6/0 7/0 8/0,这要归功于一些堆黑客,但这仍然只是纯粹的机会,并没有真正证明任何东西 (live demo)。

不幸的是,new double[4](316) 无效(根据[C++11: 8.5/16],在直接初始化期间明确禁止数组在() 内提供值)所以我们不能建议new double[4](0) 是可靠的,并使用带有 316 的示例来说服您。

【讨论】:

  • 这是为什么呢?你能指出一个参考吗?
  • 我刚试了一下,还是没有得到0。我只改了matrix = new double [columns*rows]();这一行,还是得到6.6727e-319为(3 ,2) 条目。
  • @JoBe:我添加了一个参考。你确定你重新编译了你的代码吗?
【解决方案2】:

只有静态变量在 C++ 中被初始化为 0。
自动和动态变量应该由你初始化。

【讨论】:

  • 好的,但是为什么它似乎总是为零,而 这种情况 是一个例外?
  • 只是偶然。
  • @JoBe 这是 C++ 程序员常见的早期错误:似乎注意到一种模式,然后开始依赖该模式。
  • 我明白了。但它确实看起来像 int array [5] = {}; ,不是吗?嗯,遇到错误/错误是真正学习的唯一途径,我猜
猜你喜欢
  • 1970-01-01
  • 2012-09-24
  • 2021-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-19
  • 2011-06-17
相关资源
最近更新 更多