我刚开始学习 C++,想养成良好的编程习惯。如果我使用 new
运算符分配了一个 int
类型的数组,如何才能初始化所有元素为0而不必自己循环遍历数组?我应该使用 memset
吗?还有没有更“C++”方式来实现?
我刚开始学习 C++,想养成良好的编程习惯。如果我使用 new
运算符分配了一个 int
类型的数组,如何才能初始化所有元素为0而不必自己循环遍历数组?我应该使用 memset
吗?还有没有更“C++”方式来实现?
这是一个关于C++的鲜为人知的特性(如此少有人提到,可见度极低),但它实际上有用于对数组进行值初始化的特殊语法:
new int[10]();
(0)
或任何其他形式(这就是为什么它只用于值初始化的原因)。T
的对象并将其初始化如下:()
形式,则项目进行值初始化 (8.5);(expression-list)
形式则受到同一部分中进一步规则的明确限制,因此不允许数组类型。new int[10] {}
。您还可以提供要初始化的值:new int[10]{1, 2, 3}
。 - bames53有多种方法可以分配基本类型的数组,这些方法都是正确的,但选择哪种方法取决于...
通过循环手动初始化所有元素
int* p = new int[10];
for (int i = 0; i < 10; i++)
p[i] = 0;
使用来自<cstring>
的std::memset
函数
int* p = new int[10];
std::memset(p, 0, sizeof *p * 10);
使用来自<algorithm>
的std::fill_n
算法
int* p = new int[10];
std::fill_n(p, 10, 0);
std::vector
容器std::vector<int> v(10); // elements zero'ed
int a[] = { 1, 2, 3 }; // 3-element static size array
vector<int> v = { 1, 2, 3 }; // 3-element array but vector is resizeable in runtime
int array[SIZE] ={1,2,3,4,5,6,7};
表示法,则可以使用void rotateArray(int (& input)[SIZE], unsigned int k);
作为我的函数声明,那么在使用第一种约定时会发生什么?有什么建议吗? - Anustd::memset
的示例是错误的 - 您传递了10,它似乎期望字节数 - 请参见https://en.cppreference.com/w/cpp/string/byte/memset。(我认为这很好地展示了为什么应尽可能避免使用这种低级构造。) - Suma假设你真的需要一个数组而不是 std::vector, "C++方式"就是这样
#include <algorithm>
int* array = new int[n]; // Assuming "n" is a pre-existing variable
std::fill_n(array, n, 0);
请注意,在底层实际上仍然只是一个循环,将每个元素赋值为0(除非具有硬件级别支持的特殊体系结构,否则没有其他方法可行)。
int * array = new int[n]()
- 8.8.8.8初始化动态数组的可能方式。根据您的要求选择其中一种方式。
int* x = new int[5]; // gv gv gv gv gv (gv - garbage value)
int* x = new int[5](); // 0 0 0 0 0
int* x = new int[5]{}; // 0 0 0 0 0 (Modern C++)
int* x = new int[5]{1,2,3}; // 1 2 3 0 0 (Modern C++)
如果您要分配的内存是具有执行某些有用操作的构造函数的类,则运算符new将调用该构造函数并使对象初始化。
但是,如果您要分配一个POD或者没有初始化对象状态的构造函数,则不能使用运算符new在一次操作中分配内存并初始化该内存。但是,您有几个选项:
Use a stack variable instead. You can allocate and default-initialize in one step, like this:
int vals[100] = {0}; // first element is a matter of style
use memset()
. Note that if the object you are allocating is not a POD, memsetting it is a bad idea. One specific example is if you memset a class that has virtual functions, you will blow away the vtable and leave your object in an unusable state.
Many operating systems have calls that do what you want - allocate on a heap and initialize the data to something. A Windows example would be VirtualAlloc()
.
This is usually the best option. Avoid having to manage the memory yourself at all. You can use STL containers to do just about anything you would do with raw memory, including allocating and initializing all in one fell swoop:
std::vector<int> myInts(100, 0); // creates a vector of 100 ints, all set to zero
std::vector<int> vec(SIZE, 0);
std::vector
而不是动态分配的数组吗?使用数组和向量有什么好处,反之亦然? - dreamlaxstd::fill
是其中一种方法。需要两个迭代器和一个值来填充该区域。我认为,这或者使用for循环才是更C++的方式。
对于将基本整数类型的数组设置为0,memset
是可以的,尽管可能会引起注意。考虑使用calloc
,但由于需要进行转换,因此在C++中使用有点不方便。
就我而言,我几乎总是使用循环。
(我不喜欢去猜测别人的意图,但事实上,所有条件相等时,使用std::vector
比使用new[]
更可取。)
你可以随时使用memset:
int myArray[10];
memset( myArray, 0, 10 * sizeof( int ));
10 * sizeof( *myArray )
比10 * sizeof( int )
更具有文档化和可变性。 - Kevin Reid对于C++,使用std::array<int/*类型*/, 10/*大小*/>
代替C风格数组。这是C++11标准中提供的,并且是一个好的实践方法。在这里查看标准和示例。如果出于某些原因您想坚持使用旧的C风格数组,则有两种可能的方法:
int *a = new int[5]();
这里将括号留空,否则会导致编译错误。这将初始化分配数组中的所有元素。如果您不使用括号,它仍将使用零初始化整数值,因为new将调用构造函数,在这种情况下是int()
。int *a = new int[5] {0, 0, 0};
这在C++11标准中是允许的。在这里,您可以使用任何您想要的值来初始化数组元素。在这里,请确保您的初始化列表({}中的值)大小不应大于您的数组大小。初始化列表大小小于数组大小是可以的。数组中剩余的值将被初始化为0。std::array<>
的大小必须在编译时知道。无法根据在运行时确定的大小声明 std::array<>
,因此在使用 new[]
或 std::vector<>
时,不能总是实用或可行地使用 std::array<>
。 - dreamlaxstd::vector
。
&vector[0]
。 - jamesdlin