C++函数传递引用或指针
常见变量用法
下面通过例子分别展示传递值、字符串、数组的用法
示例代码
#include <iostream>
#include <string>
// 函数接受一个整数的引用和一个整数的指针
void modifyValue(int& refValue, int* ptrValue) {
refValue = 100; // 通过引用修改值
std::cout << "Value pointed by ptrValue: " << *ptrValue << std::endl; // 通过指针打印值
}
//==========================================================================
// 函数接受一个字符串的引用
void modifyString(std::string& strRef) {
strRef += " modified";
}
//==========================================================================
// 函数接受一个指向整型数组的指针
void modifyArray(int* arrPtr, int size) {
for (int i = 0; i < size; ++i) {
arrPtr[i] += 10; // 将数组中的每个元素增加10
}
}
int main() {
int value = 10; // 声明一个整数值
int anotherValue = 20; // 声明另一个整数值
// 调用 modifyValue 函数,传递 value 的引用和 anotherValue 的地址
modifyValue(value, &anotherValue);
std::cout << "Modified value: " << value << std::endl; // 打印修改后的 value
// 打印 anotherValue,注意它不会被 modifyValue 函数修改
std::cout << "anotherValue: " << anotherValue << std::endl;
std::cout << "================================================" << std::endl;
//==========================================================================
// 调用 modifyString 函数,传递字符串的引用
std::string myString = "Original String";
modifyString(myString);
std::cout << "Modified String: " << myString << std::endl;
std::cout << "================================================" << std::endl;
//==========================================================================
// 调用 modifyArray 函数,传递数组的指针和大小
// 当传递一个数组到函数时,它会被退化为一个指向其第一个元素的指针。
// 因此,函数本身无法直接知道传入的数组的大小,因为数组的大小信息在传递时丢失了,所以必须在函数外计算数组长度。
int myArray[] = { 1, 2, 3, 4, 5 }; // 任意长度的数组
int arraySize = sizeof(myArray) / sizeof(myArray[0]); // 计算数组的大小
modifyArray(myArray, arraySize);
// 打印修改后的数组
std::cout << "Modified Array: ";
for (int item : myArray) {
std::cout << item << " ";
}
std::cout << std::endl;
return 0;
}
运行结果为
Value pointed by ptrValue: 20
Modified value: 100
anotherValue: 20
================================================
Modified String: Original String modified
================================================
Modified Array: 11 12 13 14 15
vector变量用法
给出示例
#include <iostream>
#include <vector>
// 函数接受一个 std::vector 的引用
// 如果无需修改 vector,可以传递一个常量引用。这样可以提高效率,因为编译器不需要为 vector 创建副本。(待确认?)
void printVector(const std::vector<int>& vec) {
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
}
void modifyVector1(std::vector<int> vec) {
for (int& num : vec) { // 注意:这里的修改不会影响原始的 myVector
num *= 2; // 修改 vector 中的每个元素
}
}
void modifyVector2(std::vector<int>& vec_ref) {
for (int num : vec_ref) { // 实际上为每个元素创建了副本,不会影响原始的 myVector
num *= 2; // 修改 vector 中的每个元素
}
for (int& num : vec_ref) { // 只有传进来的是引用且通过引用来访问其中的元素才会影响原始的 myVector
num *= 2; // 修改 vector 中的每个元素
}
}
void modifyVector3(std::vector<int>& vec_ref) {
int length = vec_ref.size(); // 计算 vector 的长度
for (int i = 0; i < length; ++i) {
vec_ref[i] *= 2; // 修改 vector 中的每个元素
}
}
int main() {
std::vector<int> myVector = { 1, 2, 3, 4, 5 };
modifyVector1(myVector); // 调用函数,传递 vector 的拷贝
printVector(myVector); // 打印原始 vector,其内容不会改变
modifyVector2(myVector); // 调用函数,传递 vector 的引用
printVector(myVector); // 打印 vector,其内容会改变
modifyVector3(myVector); // 调用函数,传递 vector 的引用
printVector(myVector); // 打印 vector,其内容会改变
return 0;
}
运行结果为
1 2 3 4 5
2 4 6 8 10
4 8 12 16 20
大多数情况下,传递 std::vector 的引用或常量引用是最佳选择,因为它们既能够访问 vector 的内容,又不会产生不必要的性能开销。传递指针在语法上也能实现,但据说用的不多。
补充说明
1. for (int& num : vec)
与 for (int num : vec)
的用法
这两种循环都是基于范围的 for 循环,是 C++11 引入的新特性。
for (int num : vec)
:这种用法是创建vec
中每个元素的副本。在这个循环中,num
是vec
中元素的拷贝,对num
的任何修改都不会影响原始的vec
。for (int& num : vec)
:这种用法是通过引用来访问vec
中的每个元素。在这个循环中,num
是vec
中元素的引用,对num
的任何修改都会直接反映到原始的vec
上。
应该在以下情况下使用 &
:
- 当需要修改
vector
中的元素时。 - 当处理的是大型对象,并且希望通过引用来避免不必要的拷贝,从而提高效率。
2. 推荐 std::vector
还是数组?功能上的差别(GPT生成)
一般来说,推荐使用 std::vector
而不是原生数组,因为 std::vector
提供了更多的便利和安全性。以下是两者的一些功能上的差别:
- 动态大小:
std::vector
可以在运行时动态地改变其大小,而数组的大小在编译时是固定的。 - 方便的接口:
std::vector
提供了如push_back
,pop_back
,size
,capacity
等有用的成员函数。 - 自动管理内存:
std::vector
自动管理其元素的内存分配和释放,减少了内存泄漏的风险。
以下是一个例子,展示了std::vector
和数组的功能差异:
#include <iostream>
#include <vector>
int main() {
// 使用数组
int arr[5] = {1, 2, 3, 4, 5}; // 数组大小在编译时确定
// arr.push_back(6); // 错误:数组没有 push_back 方法
// 使用 std::vector
std::vector<int> vec = {1, 2, 3, 4, 5}; // vector 可以动态改变大小
vec.push_back(6); // 添加一个新元素到 vector
// 打印 vector
for (int num : vec) {
std::cout << num << " ";
}
std::cout << std::endl;
return 0;
}
在这个例子中,我们不能对数组 arr
使用 push_back
方法,因为数组不支持动态大小。而 std::vector
可以很容易地添加新元素。
总的来说,除非有特定的性能需求或限制,否则在大多数情况下,推荐使用 std::vector
,因为它更灵活、更安全,并且更容易使用。
字符串的用法
在第一个示例的基础上进一步扩展说明字符串相关的用法。概括来讲:
- 指针:适合处理 C 风格字符串(即以空字符
\0
结尾的字符数组),允许直接操作内存,但需要小心管理内存。 - 引用:适合处理 C++ 的 std::string,语法简洁且安全,能够避免常见的字符串处理错误。
使用引用修改字符串:
#include <iostream>
#include <string>
// 修改字符串的函数,接受字符串的引用
void modifyString(std::string& str) {
str += " modified"; // 修改传入的字符串
str = "Modified string"; // 当然也可以直接修改引用对象的值
}
int main() {
std::string myString = "Original string";
std::cout << "Before modification: " << myString << std::endl;
modifyString(myString); // 调用函数,传递字符串的引用
std::cout << "After modification: " << myString << std::endl;
return 0;
}
使用指针修改字符串:
很容易出现各种bug,不推荐。
#include <iostream>
#include <cstring>
void modifyString(char* str) {
if (str != nullptr) {
// 使用strcpy_s函数修改字符串
if (strcpy_s(str, strlen("Modified string") + 1, "Modified string") != 0) {
std::cerr << "Error: Failed to modify string." << std::endl;
return;
}
}
}
int main() {
char myString[] = "Original string";
std::cout << "Before: " << myString << std::endl; // 输出: Original string
modifyString(myString);
std::cout << "After: " << myString << std::endl; // 输出: Modified string
return 0;
}