我知道指针存储它们指向的值的地址,但是如果将指针的值直接显示到屏幕上,则会得到一个十六进制数。如果数字正是指针存储的内容,那么当说
pA = pB; //both are pointers
你在复制地址。int
那么在处理像s 和bool
s这样的非常小的项目时,使用指针不会有更大的开销吗?
指针本质上只是一个数字。它将地址存储在数据所在的 RAM 中。int
指针本身非常小(可能与32 位架构long
上的 64 位上的大小相同)。
你是对的,尽管在使用sint *
时 an 不会节省任何空间。int
但这不是重点(不是双关语)。指针在那里,因此您可以引用事物,而不仅仅是使用事物本身。
内存地址。
那是内存中其他东西所在的位置。
指针通常是处理器的字长,因此它们通常可以在单个指令周期内移动。简而言之,它们很快。
正如其他人所说,指针存储的内存地址“只是一个数字”,但这是一种抽象。根据处理器架构,它可能不止一个数字,例如必须添加一个基数和偏移量以取消引用指针. 在这种情况下,开销比地址为单个数字时略高。
是的,通过指针与直接访问 int 或 bool 存在开销,处理器可以将变量放入寄存器中。指针通常用于间接值超过任何开销的地方,即遍历数组。
我一直在指时间开销。不确定 OP 是否更关心空间或时间开销。
数字是指它在内存中的地址。指针的大小通常是计算机体系结构的本机大小,因此与任何其他原始类型相比没有额外的开销。
在某些体系结构中,由于体系结构仅支持寻址字(32 位或 64 位值),因此会产生额外的字符指针开销。因此,指向字符的指针被存储为字地址和该字中字符的偏移量。取消引用指针涉及获取单词,然后移动和屏蔽它的值以提取字符。
让我从基础开始。首先,您必须知道什么是变量以及如何使用它们。
变量基本上是内存位置(通常包含一些值),我们使用一些标识符(即变量名)来引用该内存位置并使用该位置存在的值。
为了更好地理解它,假设我们希望来自内存单元的信息出现在相对于当前变量的某个位置。我们可以使用标识符从附近的单元格中提取信息吗?不,因为标识符(变量名)只会给出该特定单元格中包含的值。
但是,如果我们能以某种方式获得该变量所在的内存地址,那么我们可以轻松地移动到附近的位置并使用它们的信息(在运行时)。
这就是指针发挥作用的地方。它们用于存储该变量的位置,以便我们可以在需要时使用附加地址信息。
语法:要存储变量的地址,我们可以简单地使用& (address-of) 运算符。
foo = &bar
这里 foo 存储变量 bar 的地址。
现在,如果我们想知道该地址的值怎么办?
为此,我们可以简单地使用*(取消引用)运算符。
value = *foo
现在我们必须存储变量的地址,我们将需要内存,就像我们需要变量一样。这意味着指针也像其他变量一样存储在内存中,所以就像变量一样,我们也可以将指针的地址存储到另一个指针中。
内存中的地址。指向某个地方!:-)
是的,你是对的,无论是在速度还是内存方面。
指针几乎总是比标准占用更多的字节int
,尤其是bool
数据char
类型。在现代机器上,指针通常是 8 个字节,而char
几乎总是只有 1 个字节。
在此示例中,访问 thechar
和bool
fromFoo
需要比访问 from 更多的机器指令Bar
:
struct Foo
{
char * c; // single character
bool * b; // single bool
};
struct Bar
{
char c;
bool b;
};
...如果我们决定制作一些数组,那么数组的大小Foo
将大 8 倍 - 并且代码更加分散,因此这意味着您最终会有更多的缓存未命中。
#include <vector>
int main()
{
int size = 1000000;
std::vector<Foo> foo(size);
std::vector<Bar> bar(size);
return 0;
}
正如 dmckee 指出的那样,一个字节bool
的单个副本和一个指针的单个副本同样快:
bool num1, num2,* p1, * p2;
num1 = num2; // this takes one clock cycle
p1 = p2; // this takes another
正如 dmckee 所说,当您使用 64 位架构时,这是正确的。
但是,复制int
s、bool
s 和char
s 的数组会快得多,因为我们可以将它们的倍数压缩到每个寄存器中:
#include <iostream>
int main ()
{
const int n_elements = 100000 * sizeof(int64_t);
bool A[n_elements];
bool B[n_elements];
int64_t * A_fast = (int64_t *) A;
int64_t * B_fast = (int64_t *) B;
const int n_quick_elements = n_elements / sizeof(int64_t);
for (int i = 0; i < 10000; ++i)
for (int j = 0; j < n_quick_elements; ++j)
A_fast[j] = B_fast[j];
return 0;
}
STL 容器和其他好的库为我们做这种事情,使用type_traits
( is_trivially_copyable
) 和std::memcopy
. 在错误的幌子下使用指针总是一样快可以防止这些库优化。
结论:这些示例似乎很明显,但仅当您需要获取/授予对原始对象的访问权时,才对基本数据类型使用指针/引用。