指针与引用

在给函数使用原始变量时,更好的做法是什么:

unsigned long x = 4;


void func1(unsigned long& val) {
val = 5;
}
func1(x);

或者:

void func2(unsigned long* val) {
*val = 5;
}
func2(&x);

勒夫:有什么理由选择一个而不是另一个吗?

122148 次浏览

我的经验法则是:

如果你想对指针进行算术运算(例如,增加指针地址以遍历数组),或者如果你必须传递一个空指针,请使用指针。

否则使用引用。

我真的认为你将受益于建立以下函数调用编码指南:

  1. 像在所有其他地方一样,始终是const-correct。

    • 注意:这意味着,除其他外,只有out-value(参见第3项)和通过value传递的值(参见第4项)可以缺少const说明符。
    • 李< / ul > < / >
    • 只有当值0/NULL在当前上下文中是有效输入时,才通过指针传递值。

      • 原理1:当调用者时,可以看到在中传递的任何东西都必须是处于可用状态。

      • 原理2:由于称为,您知道在中出现的任何东西都是处于可用状态。因此,不需要对该值进行null检查或错误处理。

      • 基本原理3:基本原理1和2将是编译器强制。如果可以,总是在编译时捕获错误。

      • 李< / ul > < / >
      • 如果函数参数是out-value,则通过引用传递。

        • 理由:我们不想破坏第2项……
        • 李< / ul > < / >
        • 只有当值是POD (普通的旧式数据结构)或足够小(内存方面)或以其他方式足够便宜(时间方面)可以复制时,才选择“按值传递”而不是“按const引用传递”。

          • 理由:避免不必要的拷贝。
          • 注意:足够小足够便宜不是绝对可测量值。
          • 李< / ul > < / >

通过const引用传递,除非有原因你希望改变/保留你传递的内容。

在大多数情况下,这将是最有效的方法。

确保对不想更改的每个形参都使用const,因为这不仅可以防止您在函数中做一些愚蠢的事情,还可以很好地向其他用户指示函数对传入的值做了什么。这包括当你只想改变所指向的对象时,创建一个const指针…

这最终是主观的。到目前为止的讨论是有用的,但我不认为有一个正确或决定性的答案。这在很大程度上取决于风格指南和您当时的需求。

虽然指针有一些不同的功能(是否可以为NULL),但输出参数的最大实际差异纯粹是语法。例如,谷歌的c++样式指南(https://google.github.io/styleguide/cppguide.html#Reference_Arguments)只要求输出参数的指针,并且只允许const类型的引用。原因是可读性:具有值语法的东西不应该具有指针语义。我并不是说这一定是对的或错的,但我认为这是风格的问题,而不是正确性的问题。

引用是隐式指针。基本上,你可以改变引用指向的值,但你不能改变引用指向其他东西。因此,我的观点是,如果你只想改变一个参数的值,将其作为引用传递,但如果你需要改变参数以指向一个不同的对象,则使用指针传递它。

如果你要修改变量的值,你应该传递一个指针。 尽管从技术上讲传递引用或指针是相同的,但在您的用例中传递指针更具有可读性,因为它“发布”了函数将更改值的事实

如果你有一个参数,你可能需要指出没有一个值,通常的做法是使参数为指针值并传递NULL。

在大多数情况下(从安全的角度来看),更好的解决方案是使用boost::可选。这允许您通过引用传递可选值,也可以作为返回值。

// 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#的out关键字。编译器要求方法的调用者将out关键字应用于任何out参数,即使它已经知道它们是否存在。这是为了提高可读性。尽管在现代ide中,我倾向于认为这是语法(或语义)突出显示的工作。

可以时使用引用,必要时使用指针。 从c++常见问题:“什么时候应该使用引用,什么时候应该使用指针?” < / p >

指针:

  • 可以赋值为nullptr(或NULL)。
  • 在调用站点,如果你的类型本身不是指针,你必须使用&
  • 指针可以被反弹。

引用:

  • 不能为空。
  • 一旦被束缚,就无法改变。
  • 调用者不需要显式地使用&。有时这被认为是 不好,因为你必须去函数的实现看看 完成参数的修改。李< / >

指针

  • 指针是保存内存地址的变量。
  • 指针声明由基类型、*和变量名组成。
  • 指针在生命周期内可以指向任意数量的变量
  • 当前不指向有效内存位置的指针被赋值为null(为零)

    BaseType* ptrBaseType;
    BaseType objBaseType;
    ptrBaseType = &objBaseType;
    
  • The & is a unary operator that returns the memory address of its operand.

  • Dereferencing operator (*) is used to access the value stored in the variable which pointer points to.

       int nVar = 7;
    int* ptrVar = &nVar;
    int nVar2 = *ptrVar;
    

Reference

  • A reference (&) is like an alias to an existing variable.

  • A reference (&) is like a constant pointer that is automatically dereferenced.

  • It is usually used for function argument lists and function return values.

  • A reference must be initialized when it is created.

  • Once a reference is initialized to an object, it cannot be changed to refer to another object.

  • You cannot have NULL references.

  • A const reference can refer to a const int. It is done with a temporary variable with value of the 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
    

enter image description here

enter image description here

引用类似于指针,除了不需要使用前缀*来访问引用所引用的值。同样,在初始化对象之后,不能引用另一个对象。

引用对于指定函数参数特别有用。

有关更多信息,请参阅“Bjarne Stroustrup”(2014)的“c++之旅”(A Tour of c++)第11-12页