问题记录
这里对工作中遇到的C++问题进行记录
具体记录
1.C++中int a[10]= {0,1,2,3,4,5,6,7,8,9}
,其中的a+3
代表什么意思?
在数组中,数组名实际上是指向数组首元素的指针,因此a+3
指向数组首地址后偏移3个元素 的地址,在这个例子中a+3
指向的是数组中第四个元素的地址,即整数3的地址
memcpy踩坑记录
void *memcpy(void *destin, void *source, unsigned n);
函数的功能是从源内存地址的起始位置开始拷贝若干个字节到目标内存地址中,即从源source中拷贝n个字节到目标destin中,注意这里的n 的单位是字节。
如果是memcpy(a,a+3,2)
出现的结果就是3,1,2,3,4,5,6,7,8,9。一个int 类型占用的字节数为4,这里只是有两个字节的内容替换。如果是两个地方的需要替换,则是需要在memcpy后面的参数进行修改,memcpy(a,a+3,2*sizeof(int))
,这样的结果就是3,4,2,3,4,5,6,7,8,9。
2 C++中值传递,地址传递,引用传递
(1)值传递
- 参数传递方式:将实际参数的值传递给函数的形式参数
- 特点:在函数内部修改形式参数的值不会影响实际参数的值。形式参数的改变只在函数内部有效
- 优点:简单,不会影响实际参数的值
- 缺点:传递大型数据时可能效率较低,因为需要复制整个数据结构。
#include <iostream>
void increment(int x) {
x++;
}
int main() {
int num = 5;
increment(num);
std::cout << num << std::endl; // 输出仍然是5,因为在函数内部修改的是形式参数的值
return 0;
}
(2)地址传递
- 参数传递方式:将实际参数的地址传递给函数的形式参数(通过指针)
- 特点:在函数内部修改形式参数指向的内存中的值会影响实际参数的值
- 优点:对于大型数据结构,不需要复制整个结构,只需要传递地址,可以提高效率
- 缺点:需要注意指针的合法性,可能会引入到操作的复杂性
#include <iostream>
void increment(int *x) {
(*x)++;
}
int main() {
int num = 5;
increment(&num);
std::cout << num << std::endl; // 输出为6,因为在函数内部通过指针修改了实际参数的值
return 0;
}
总得来说,值传递适用于小型数据结构,而地址传递适用于大型数据结构,因为后者避免了复制整个数据结构的开销。
补充:
指针的加法涉及到指针地址的加法,而不是对地址上的数据进行加法操作。当你对指针进行加法操作时,指针会根据它所指定的数据类型大小,以字节为单位移动相应的地址。这是因为指针的类型决定了它在内存中移动的步长。例如,一个整形指针intPtr
指向地址0x1000
,当执行intPtr++
,那么这个时候intPtr
地址为0x1004
,对指针进行操作的时候,它会移动到sizeof(int)
的距离。
#include <iostream>
int main() {
int array[5] = {1, 2, 3, 4, 5};
int *intPtr = array; // intPtr指向数组的第一个元素
std::cout << "Original Address: " << intPtr << std::endl;
intPtr++; // 移动指针到下一个元素
std::cout << "New Address: " << intPtr << std::endl;
return 0;
}
- int num = 5;:在 main 函数中,一个整型变量 num 被初始化为5
- increment(&num);:&num 取得 num 的地址,将该地址传递给 increment 函数。在 increment 函数内部,通过指针对实际参数的值进行递增操作,即 (*x)++,其中 x 是指向 num 的指针。
- 递增操作 (*x)++ 相当于将 num 的值增加1。因此,num 的值从5变为6。
- std::cout << num << std::endl;:在 main 函数中输出 num 的值,这时 num 的值已经变为6,所以输出为6。
因此,最终输出结果为6。这展示了通过指针修改实际参数的值,使得 main 函数中的 num 在 increment 函数的影响下被增加了
(3)引用传递和指针传递 - 参数的传递方式:使用引用作为函数的参数
- 语法:使用“&”符号声明引用类型,如“int &ref”
- 特点:在函数内部修改引用的值会直接影响到实际参数的值
- 优点:更直观,简洁,无需通过指针解引用操作
#include <iostream>
void increment(int &x) {
x++;
}
int main() {
int num = 5;
increment(num);
std::cout << num << std::endl; // 输出为6
return 0;
}
指针传递(Pointer Passing)
- 参数传递方式:使用指针作为函数的参数
- 使用“*”符号声明指针类型,如“int * ptr”
- 特点:需要通过指针解引用操作来访问或修改实际参数的值
- 优点:提供更多的灵活性,可以通过改变指针的指向操作来操作不同的数据
#include <iostream>
void increment(int *x) {
(*x)++;
}
int main() {
int num = 5;
increment(&num);
std::cout << num << std::endl; // 输出为6
return 0;
}
- 语法差异: 引用使用 &,指针使用 *。
- 使用方式: 引用更直观,不需要显式地进行指针解引用,而指针提供了更多的灵活性。
- Null 值: 引用不能为 null,而指针可以为 null。
- 初始化: 引用在创建时必须初始化,并且一旦引用被指定了某个变量,就不能再引用其他变量。指针可以在后续进行赋值。
- 传递对象: 当传递对象时,引用更直观且通常更安全;指针可以传递 null,并且可以通过指针算术运算访问不同的数据。