我的问题很简单:std :: vector元素是否保证是连续的?在order word中,我可以使用指向std :: vector的第一个元素的指针作为C数组吗?
如果我的记忆力很好,那么C++标准就没有这样的保证.但是,如果元素不连续,那么std :: vector要求几乎不可能满足它们.
有人可以澄清一下吗?
例:
std::vector<int> values;
// ... fill up values
if( !values.empty() )
{
int *array = &values[0];
for( int i = 0; i < values.size(); ++i )
{
int v = array[i];
// do something with 'v'
}
}
Run Code Online (Sandbox Code Playgroud) 我希望存储一个大的d维点矢量(d固定和小:<10).
如果我定义一个Point
as vector<int>
,我认为a vector<Point>
会在每个位置存储指向Point的指针.
但是,如果将a定义Point
为固定大小的对象,如:
std::tuple<int,int,...,int>
或者std::array<int, d>
,程序是否会将所有点存储在连续的内存中,还是会保留额外的间接级别?
如果答案是数组避免额外的间接,那么在扫描时,这会对性能(缓存利用局部性)产生很大影响vector<Point>
吗?
在C++ 11 std::array
中定义的连续存储和性能并不比数组差,但我不能确定标准的各种要求是否意味着std :: array具有与普通数据相同的大小和内存布局阵列.那是你可以指望的sizeof(std::array<int,N>) == sizeof(int)*N
还是具体的实施?
特别是,这保证按照您期望的方式工作:
std::vector< std::array<int, N> > x(M);
typedef (*ArrayPointer)[N];
ArrayPointer y = (ArrayPointer) &x[0][0];
// use y like normal multidimensional array
Run Code Online (Sandbox Code Playgroud)
它适用于我尝试过的两个编译器(GNU和Intel).此外,我能找到的所有第三方文档(如下所示)都表明std :: array与普通数组一样具有内存效率,它与连续需求相结合意味着它必须具有相同的内存布局.但是我在标准中找不到这个要求.
请考虑以下代码:
int a[25][80];
a[0][1234] = 56;
int* p = &a[0][0];
p[1234] = 56;
Run Code Online (Sandbox Code Playgroud)
第二行是否调用未定义的行为?第四行怎么样?
c++ arrays pointers multidimensional-array undefined-behavior
我有一个关于C/C++如何在内部存储使用符号声明的多维数组的问题foo[m][n]
.我不是在质疑指针的纯指针等等......因为速度原因,我在问...
如果我错了,请纠正我,但语法上foo
是一个指针数组,它们本身指向一个数组
int foo[5][4]
*(foo + i) // returns a memory address
*( *(foo + i) + j) // returns an int
Run Code Online (Sandbox Code Playgroud)
我从很多地方听说过C/C++编译器foo[m][n]
在幕后转换为一维数组(计算所需的一维索引i * width + j
).但是如果这是真的那么以下就可以了
*(foo + 1) // should return element foo[0][1]
Run Code Online (Sandbox Code Playgroud)
因此我的问题foo[m][n]
是:(总是吗?)存储在内存中作为平面一维数组是真的吗?如果是这样,为什么上面的代码如图所示.
除了标准将其定义为连续的事实之外,为什么std :: vector是连续的?
如果空间不足,则需要重新分配新块并将旧块复制到新块,然后再继续.
如果它不连续怎么办?当存储填满时,它只会分配一个新块并保留旧块.当通过迭代器访问时,它会执行简单的>,<检查以查看索引所在的块并将其返回.这样,每次空间不足时都不需要复制数组.
这会真的有用吗?还是我错过了什么?
有很多像这样的代码:
#include <stdio.h>
int main(void)
{
int a[2][2] = {{0, 1}, {2, -1}};
int *p = &a[0][0];
while (*p != -1) {
printf("%d\n", *p);
p++;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但基于这个答案,行为是不确定的.
N1570.6.5.6 p8:
当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型.如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.换句话说,如果表达式P指向数组对象的第i个元素,则表达式(P)+ N(等效地,N +(P))和(P)-N(其中N具有值n)指向分别为数组对象的第i + n和第i-n个元素,只要它们存在.此外,如果表达式P指向数组对象的最后一个元素,则表达式(P)+1指向一个超过数组对象的最后一个元素,如果表达式Q指向一个超过数组对象的最后一个元素,表达式(Q)-1指向数组对象的最后一个元素.如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.如果结果指向数组对象的最后一个元素之后,则不应将其用作已计算的一元*运算符的操作数.
有人可以详细解释一下吗?