设置整个数组的值的最简单方法是啥?
Posted
技术标签:
【中文标题】设置整个数组的值的最简单方法是啥?【英文标题】:What is the easiest way to set the value of an entire array?设置整个数组的值的最简单方法是什么? 【发布时间】:2010-06-09 22:20:02 【问题描述】:我当前的项目要求我根据其他一些值填充一个数组。我知道有捷径:
int arr[4][4] = 0,0,0,0 , 0,0,0,0 , 0,0,0,0 , 0,0,0,0 ;
但在这种情况下,我需要在声明后填充数组。我目前的代码格式如下:
int arr[4][4];
if(someothervariable == 1)
arr = 1,1,1,1,
1,2,3,4,
2,,3,4,5,
3,4,5,6 ;
但它不会编译。在我的情况下,有没有办法使用提到的快捷方式?如果没有,最好的修复方法是什么?我很欣赏一种无需显式分配每个元素即可设置它的方法?即:arr[0][0] = ...
【问题讨论】:
原文中有多余的逗号吗? 在第一种情况下,快捷方式是int arr[4][4] =
。你上面的肯定是一个“长切”:))
C++1x 以其统一的初始化语法来拯救!不幸的是,它尚未广泛使用。
【参考方案1】:
使用 std::copy() 怎么样?
int arr[4][4];
if(someothervariable == 1)
const static int a2[4][4] = 1,1,1,1,
1,2,3,4,
2,3,4,5,
3,4,5,6 ;
std::copy(&a2[0][0], &a2[0][0]+16, &arr[0][0]);
【讨论】:
这将在实践中起作用,但从正式和迂腐的角度来说,将 2D 数组重新解释为 1D 数组是非法的。更准确地说,在&a2[0][0]
上使用距离该指针超过 4 步的指针算术在形式上是非法的。做&a2[0][0] + 16
是未定义的行为。同样,这将通常在实践中起作用。
感谢您让我重新阅读标准!我记住了the same array object
(5.7/6)和arrays in C++ are stored row-wise
(8.3.4/9)这两个词,但你是对的,在每行之间实现一个带有填充字节的二维数组是合法的(就像它拥有 &arr 是合法的(在数组到指针的转换之前)!= &arr[0][0]),在这种情况下会失败。【参考方案2】:
不,数组初始化语法用于数组初始化。不过,如果所有值都是相同的字节,则可以使用 memset。
boost.assign 库为修改/填充集合添加了一些有趣的语法,但 AFAIK 它不支持 C 样式数组(仅支持 C++ 和 Boost 容器)。
【讨论】:
【参考方案3】:在当前版本的 C++ 语言中,唯一的方法是从一些原始版本中复制它
int arr[4][4];
if (someothervariable == 1)
const int SOURCE[4][4] = // make it `static` if you prefer
1, 1, 1, 1,
1, 2, 3, 4,
2, 3, 4, 5,
3, 4, 5, 6
;
assert(sizeof arr == sizeof SOURCE); // static assert is more appropriate
memcpy(&arr, &SOURCE, sizeof arr);
如果编译器不够聪明,无法自行优化,源“常量”可以声明为static
,以避免重新初始化。
在该语言的未来版本中,计划提供类似于 C 的复合文字的功能,这将支持立即初始化(基本上是您在原始帖子中尝试做的)。
【讨论】:
这有一个C++
标记(不是C
标记),所以我更喜欢std::copy()
(并希望它在适当的时候回退到std::memcpy()
)。 Cubbi did that right.
@sbi:不幸的是,数组类型在 C++ 中是不可分配的,这就是为什么没有立即合法的基于 std::copy
的解决方案。 Cubbi 做错了(正式地说),因为他将 2D 数组重新解释为 1D 数组。这在 C++ 中是形式上非法的,并且迂腐(调试)实现有权在该代码上崩溃。一个std::copy
没有优雅的解决方案。您必须进行嵌套复制才能以正确的方式复制 2D 数组。
你说得有道理。虽然我无法想象二维数组不连续的实现,但如果是,使用std::memcpy()
会一样好。
哈!除非您不使用内置插件!然后,使用std::copy()
会导致“更少的UB”,然后使用std::memcpy()
会。 :)
【参考方案4】:
如果你想用单个值填充数组:
#include<algorithm>
#include<vector>
// ...
std::vector<int> arr;
std::fill(arr.begin(), arr.end(), VALUE); // VALUE is an integer
如果你想计算每个元素的值:
struct get_value
int operator()() const /* calculate and return value ... */
;
std::generate(arr.begin(), arr.end(), get_value());
【讨论】:
【参考方案5】:如果您将所有内容都设置为相同的值(例如零),您也许可以逃脱...
memset (arr, 0, sizeof (arr));
请注意,这充满了危险。你必须知道你的字体大小和所有的爵士乐。
但是,这似乎对您来说还不够。如果你想用不同的值填充数组,我只能想到两种方法。
方法#1。 (可能会很痛)
arr[0][0] = 1;
...
arr[0][3] = 1;
arr[1][0] = 1;
...
arr[1][3] = 4;
arr[2][0] = 2;
...
arr[2][3] = 5;
arr[3][0] = 3;
...
arr[3][3] = 6;
方法#2。 预定义一组数组,并使用指针在它们之间切换;
int arr1[4][4] =
0,0,0,0,
0,0,0,0,
0,0,0,0,
0,0,0,0 ;
int arr2[4][4] =
1,1,1,1,
1,2,3,4,
2,,3,4,5,
3,4,5,6 ;
int *arr[4];
现在您只需要设置 *arr[] 的四 (4) 个值,而不是设置所有内容。当然,这只有在你的数组将被预先确定的常量填充时才有效。
希望这会有所帮助。
【讨论】:
我想你的意思是int (*arr)[4]
。在 C++ 中,不妨这样做:int (&arr)[4] = (someothervariable == 1) ? arr2 : arr1
.【参考方案6】:
我不确定我是否喜欢这个解决方案,但是如果你将数组包装在一个结构中,那么 C/C++ 会给你分配方便,而代价是必须使用结构名称来获取数组:
typedef struct
int data[4][4];
info_t;
info_t arr;
if (someothervariable == 1)
static const info_t newdata = // since this is static const, there generally
// won't be a copy - that data will be 'baked'
// into the binary image (or at worst a
// single copy will occur)
1,1,1,1,
1,2,3,4,
2,3,4,5,
3,4,5,6
;
arr = newdata; // easy to assign new data to the array
int somethingelse = arr.data[1][2]; // a tiny bit less convenient to get
// to the array data
【讨论】:
这是 C++,所以typedef
不是必需的。 (顺便说一句,他的不便可以通过重载operator[]
为info_t
来克服。)【参考方案7】:
int arr[4][4];
if (someothervariable == 1)
int tmp[4][4] = 1, 1, 1, 1, 1, 2, 3, 4, 2, 3, 4, 5, 3, 4, 5, 6 ;
arr = tmp;
【讨论】:
数组不可赋值。arr = tmp
不会编译。以上是关于设置整个数组的值的最简单方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章