动态内存分配有不希望的输出 [英] Dynamic memory allocation has undesired output
问题描述
所以我上周开始学习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 for(j = 0; j< rows; j ++){
cout<矩阵[列* i + j] ;
}
cout<< \\\
;
}
return;
}
int * getMatrix();
int main(){
矩阵矩阵(getMatrix());
matrix.printMatrix();
matrix.free();
return 0;
}
int * getMatrix(){
int * dim = new int [2];
cout<< (m×n)-Matrix,m;
cin>> dim [0]
cout<< n?;
cin>> dim [1];
return dim;
}
当我选择一个(4, 2)矩阵。根据各种教程的理解,
matrix = new double [columns * rows]
应该分配这么多内存: columns * rows (双)。此外,每个单元格应使用 0 初始化。
但是,选择一个输出的函数printMatrix():
0 0
0 0
0 6.6727e-319
0 0
为什么
此外,每个cell都应该用0初始化。
当你写 new double [N]
时,语言不会为你这么做。
为什么(3,2)条目不用0初始化?
如果写入 new double [N]()
instead!
11:5.3.4 / 15]:
创建T
类型的对象的 new-expression 如下:
- 如果省略了 new-initializer ,则对象是 default-initialized (8.5)。
- 否则, new-initializer 将根据8.5的初始化规则解释为 direct - 初始化。
授予,这有点模糊,正在谈论非数组版本的 new
,但实际上它意味着两者; T
是 double [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.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 std :: cout< a [i]< '/'<< b [i]< '';
std :: cout<< '\\\
';
delete [] a;
delete [] b;
}
我设法获得 0/0 6/0 7/0 8/0
,由于一些堆hackery,但它仍然只是纯粹的机会,并没有真正展示任何东西( new double [4]。[/ b] (316)无效(在直接初始化期间,()
中的值明确禁止数组> [C ++ 11:8.5 / 16]
),所以我们不能建议 new double [4] code>将是可靠的,并使用
316
的示例来说服您。
So I started learning C++ last week and naturally, I want to become familiar with the whole pointer and object-oriented business and so on and so forth.
To do that, I'm writing a very simple program for some basic matrix calculations:
# 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;
}
The problem (as I see it) occurs when I choose a (4,2) matrix. As I understand from various tutorials,
matrix = new double [columns*rows];
should allocate this much memory: columns*rows times sizeof(double). Also, every 'cell' should be initialized with a 0.
But, choosing a (4,2) matrix, I get the following output, of the function printMatrix():
0 0
0 0
0 6.6727e-319
0 0
Why is the (3,2) entry not initialized with 0?
Thanks!
Also, every 'cell' should be initialized with a 0.
Nope. The language does not do that for you, when you write new double[N]
.
Why is the (3,2) entry not initialized with 0?
It will if, you write new double[N]()
instead!
[C++11: 5.3.4/15]:
A new-expression that creates an object of typeT
initializes that object as follows:
- If the new-initializer is omitted, the object is default-initialized (8.5); if no initialization is performed, the object has indeterminate value.
- Otherwise, the new-initializer is interpreted according to the initialization rules of 8.5 for direct-initialization.
Granted, this is slightly ambiguous in that it would seem to be talking about the non-array versions of new
, but in fact it means both; T
is double[4]
.
In fact, we can see that the same section of wording talks about "object" in both the array and non-array cases, setting the perfect precedent:
[C++11: 5.3.4/1]:
[..] If the entity is a non-array object, the new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer to the initial element of the array.
Now, it's essentially impossible to prove this rule, because you can strike unlucky and get all-zeroes even when those values are in fact indeterminate, but the following code entirely unconvincingly makes a good start:
#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;
}
I managed to get 0/0 6/0 7/0 8/0
from it, thanks to some heap hackery, but it's still only just pure chance and doesn't really demonstrate anything (live demo).
Unfortunately, new double[4](316)
isn't valid (providing a value inside the ()
is explicitly banned for arrays during direct-initialization, per [C++11: 8.5/16]
) so we can't suggest that new double[4](0)
would be reliable and use the example with 316
to convince you of it.
这篇关于动态内存分配有不希望的输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!