使用变量与指向变量的指针作为函数的参数
Using variables versus pointers to variables as parameters for a function
当函数需要一个指针作为参数(而不是指针引用的变量)时,这仅仅是因为传递给函数的值的大小吗?
我可以理解为什么有人想将指针传递给数组或结构,而不是传递整个数组或结构?但他们做出这一决定的其他原因是什么?例如,一个函数需要指向int
(4字节)的指针,而不是指向int
(4个字节)本身。
如果您希望函数更改参数(如int
)的值,则必须传入指向它的指针。否则,函数所做的任何更改都将在副本上进行。
通常,C和C++中所谓的"输出参数"通常是指向受函数影响的任何变量的指针。
至于数组,C实际上不允许将大块内存传递给函数,因此我们别无选择,只能传递指针。
(编辑:正如评论中所讨论的,这个答案只适用于指针。在C++中,也可以使用引用)
在C++中你会按值传递内置类型,除非你想在方法或函数中修改它们,并将修改应用于原始变量。
您可以通过引用或指针传递。如果要修改输入,有些人更喜欢传递指针,因为它更明确,因为你必须取消引用指针。
IE:
void foo(int& a, int* b)
{
a = 1; // This modifies the external variable, but you can't see that just looking at this line
*b = 1; //explicitly modifying external variable
}
int z = 0;
int y = 0;
foo(y, &z); //z is explicitly being allowed to be modified, that y can be too isn't apparent until you look at the function declaration.
其他人认为这种传球方式很难看,不喜欢
传递大型类型的最佳实践是通过const引用,它表示您不会修改实例。
一行中的答案是:如果您处理的是非基本类型的输入参数,则传递-(指针/引用)-到const,如果您处理基本类型的输出参数,则通过值传递,否则通过-(指针/引用)。正如评论中所指出的(感谢TonyD),最后一条"规则"是对使用pass-by-(指针/引用)-to const的优化;这可能没有必要,但值得一提。请注意,通过对const的引用传递不会影响使用临时参数(无论是文字参数还是函数调用的结果)调用函数的能力。
为了恰当地回答这个问题,必须做出一些区分。首先,C和C++是两种不同的野兽:C中唯一的选项是按值传递(pbv)、按指针传递(pbp)和按指针传递到常量(pbptc)。在C++中,您还可以选择通过引用传递(pbr)和通过引用传递常量(pbrtc)。第二,输入参数和(输入/)输出参数之间存在区别;当一个参数属于第二类时,除了pbp或pbr(如果可应用,即如果使用c++),您没有其他选择。至于输入参数,需要考虑的因素更为微妙。Alexandrescu在他的书"现代C++"中谈到了这个问题
您有时需要回答以下问题:给定任意类型T,传递和接受T类型的对象作为函数的参数?一般来说最有效的方法是通过引用和标量传递详细的类型按值类型。(标量类型由算术类型组成以及枚举、指针和指向成员。)对于复杂的类型,您可以避免额外的开销临时的(构造函数加上析构函数调用),对于标量类型您可以避免由参考
(当然,对于输入参数,他指的是pbrtc)。同样,您应该选择pbptc来处理C.中的"精细"类型
最后,如果你使用C++,你可以通过使用"类型特征"(无论是标准的还是自定义的,请参阅现代C++了解更多信息)来自动进行这种选择。类型特征允许你自动知道一个类型是否是基本类型,是否已经是引用(在这种情况下,你不能通过引用传递它,因为C++不允许引用引用)以及所有有意义的东西。例如,通过type_traits
,您可以编写这样的
#include <type_traits>
typedef int& my_type;
void f(const std::add_lvalue_reference<my_type> a){
}
typedef int my_type2;
void g(const std::add_lvalue_reference<my_type2> a){
}
int main() {
}
当然,这是一个虚构的例子,但你可以看到这种方法的实用性,如果你使用模板,它会更大。注意,type_traits
是c++11std库的一部分,如果您不使用c++11,则必须制作自己的(或使用某个库作为loki)
当您想要更改int
变量时,您也可以使用reference。
对于数组,数组名称只是指向第一个元素的指针,当它用作传递给函数的参数时,它将变为普通指针,因此必须将数组中元素的数量作为参数传递。
使用变量与指向变量的指针作为函数的参数
一般建议:
-
如果函数不更改参数,则按值传递。
#include <iostream> int test(int arg){ std::cout << arg; } int main(int argc, char** argv){ int a = 6; test(a); return 0; }
-
如果函数需要更改传递的参数,请通过引用传递。
#include <iostream> int test(int &arg){ arg = 6; } int main(int argc, char** argv){ int a = 0; test(a); std::cout << arg; return 0; }
- 如果函数不需要更改参数,但参数是BIG,则通过const引用传递
-
如果函数需要更改传递的参数AND,则此参数是可选的,通过指针传递。
#include <iostream> int test(int *arg){ if (arg) *arg = 6; } int main(int argc, char** argv){ int a = 0, b = 1; test(0); test(&b); std::cout << a << std::endl << b << std::endl; return 0; }
-
如果一个函数不需要更改传递的参数,参数是大的,参数是可选的,则通过指向常量的指针传递。
推理:引用和指针可以用于修改函数"外部"的值,但引用不能设置为0/NULL。
指向int(4字节)的指针
根据平台的不同,指向int的指针可能不是4字节大。例如,在64位系统上,它将有8字节大。
如果该函数分配内存块,则返回指向int的指针是有意义的。如果此函数用作"选择器"并且需要写入返回值,则将指针/引用返回到int是有意义的。
#include <iostream>
int& getMaxVal(int &a, int &b){
return (a > b)? a: b;
}
int main(int argc, char** argv){
int i = 3, j = 4;
std::cout << i << " " << j << std::endl;
getMaxVal(i, j) /= 2;
std::cout << i << " " << j << std::endl;
return 0;
}
- 是否可以将变量/函数返回作为模板参数传递
- 是否有一种方法可以修复编译器未找到特定的OPENCV变量/函数
- 访问实例化类的变量/函数
- 如何在变量函数参数列表中检测给定类型的参数的可用性,并在处理完所有参数后采取行动
- C 多组变量函数参数
- 最有cpu效率的方法是使用std::算法和变量函数模板的参数
- 在此作用域中未声明条件变量函数
- C 关于将数组复制到向量并调用其变量 /函数
- 仅在C 中的一个变量上,两个变量函数的数值集成(使用数值配方库)
- 在应用变量函数的矩阵元素上循环
- 如何向调试器隐藏变量/函数名
- C++11变量函数类型模板参数
- 变量函数参数的奇怪问题
- C++变量函数和cout
- c++模板变量函数未定义引用
- 我可以使用枚举类值作为变量函数的参数吗?
- 从另一个类访问变量/函数
- <"变量/函数"的多重定义>
- 从c++到C文件中定义的变量/函数的未定义引用
- 为什么转换变量函数参数很重要?