为函数提供要使用的原始变量时,有什么更好的做法:
unsigned long x = 4;
void func1(unsigned long& val) {
val = 5;
}
func1(x);
或者:
void func2(unsigned long* val) {
*val = 5;
}
func2(&x);
IOW:有什么理由选择一个而不是另一个吗?
我的经验法则是:
如果您想对指针进行指针运算(例如,递增指针地址以逐步遍历数组)或者您必须传递一个 NULL 指针,请使用指针。
否则使用参考。
我真的认为您将从建立以下函数调用编码指南中受益:
与所有其他地方一样,始终保持const
正确。
const
符。如果值 0/NULL 是当前上下文中的有效输入,则仅通过指针传递值。
理由 1:作为调用者,您看到您传入的任何内容都必须处于可用状态。
理由 2:正如所谓的那样,您知道进来的任何东西都处于可用状态。因此,不需要对该值进行 NULL 检查或错误处理。
理由 3:理由 1 和 2 将由编译器强制执行。如果可以的话,总是在编译时捕获错误。
如果函数参数是输出值,则通过引用传递它。
仅当值是 POD(普通旧数据结构)或足够小(内存方面)或以其他方式足够便宜(时间方面)进行复制时,才选择“按值传递”而不是“按 const 引用传递” 。
这最终是主观的。到目前为止的讨论很有用,但我认为对此没有正确或决定性的答案。很大程度上取决于风格指南和您当时的需求。
虽然指针有一些不同的功能(是否可以为 NULL),但输出参数的最大实际差异是纯语法。例如, Google 的 C++ 样式指南 ( https://google.github.io/styleguide/cppguide.html#Reference_Arguments ) 只要求输出参数的指针,并且只允许 const 引用。推理是可读性之一:具有值语法的东西不应该具有指针语义。我并不是说这一定是对还是错,但我认为这里的重点是风格问题,而不是正确性问题。
指针
当前未指向有效内存位置的指针被赋予值 null(为零)
BaseType* ptrBaseType;
BaseType objBaseType;
ptrBaseType = &objBaseType;
& 是一个一元运算符,它返回其操作数的内存地址。
解引用运算符 (*) 用于访问存储在指针指向的变量中的值。
int nVar = 7;
int* ptrVar = &nVar;
int nVar2 = *ptrVar;
参考
引用 (&) 类似于现有变量的别名。
引用 (&) 类似于自动取消引用的常量指针。
它通常用于函数参数列表和函数返回值。
引用必须在创建时进行初始化。
一旦一个引用被初始化为一个对象,就不能改变它来引用另一个对象。
您不能有 NULL 引用。
一个 const 引用可以引用一个 const int。它是使用具有 const 值的临时变量完成的
int i = 3; //integer declaration
int * pi = &i; //pi points to the integer i
int& ri = i; //ri is refers to integer i – creation of reference and initialization
如果要修改变量的值,则应该传递一个指针。尽管在技术上传递引用或指针是相同的,但在您的用例中传递指针更具可读性,因为它“宣传”了值将被函数更改的事实。
如果您有一个可能需要指示缺少值的参数,通常的做法是将该参数设为指针值并传入 NULL。
在大多数情况下(从安全角度来看)更好的解决方案是使用boost::optional。这允许您通过引用传递可选值,也可以作为返回值。
// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
if (optional_str)
{
cout << *optional_str << std::endl;
}
else
{
cout << "(no string)" << std::endl;
}
}
// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
if (return_nothing)
{
return boost::optional<int>();
}
return boost::optional<int>(42);
}
尽可能使用引用,必要时使用指针。来自C++ FAQ:“什么时候应该使用引用,什么时候应该使用指针?”
引用是隐式指针。基本上,您可以更改引用指向的值,但不能更改引用以指向其他内容。所以我的 2 美分是,如果您只想更改参数的值,请将其作为引用传递,但如果您需要更改参数以指向不同的对象,请使用指针传递它。
考虑 C# 的 out 关键字。编译器要求方法的调用者将 out 关键字应用于任何 out args,即使它已经知道它们是否存在。这是为了提高可读性。尽管使用现代 IDE,我倾向于认为这是语法(或语义)突出显示的工作。
通过 const 引用传递,除非您有理由希望更改/保留您传入的内容。
在大多数情况下,这将是最有效的方法。
确保在您不想更改的每个参数上使用 const,因为这不仅可以防止您在函数中做一些愚蠢的事情,而且可以很好地向其他用户表明该函数对传入的值做了什么。这包括当您只想更改指向的内容时创建一个指针 const...
指针:
nullptr
(或NULL
)。&
如果您的类型本身不是指针,则必须使用,明确表示您正在修改您的对象。参考:
&
. 这有时被认为是不好的,因为你必须去函数的实现看看你的参数是否被修改。引用类似于指针,不同之处在于您不需要使用前缀 * 来访问引用所引用的值。此外,在初始化后不能引用另一个对象。
引用对于指定函数参数特别有用。
有关更多信息,请参阅“Bjarne Stroustrup”(2014 年)第 11-12 页的“C++ 之旅”