什么时候对函数的引用有用?

时间:2015-02-25 01:47:38

标签: c++

对数组参数的引用很有用,因为它可以防止衰减,从而可以推断出数组的大小。

template <typename T, std::size_t N>
constexpr std::size_t array_size(T (&) [N]) noexcept
{
  return N;
}

但这什么时候有用?

template<typename T>
void foo(T& t)
{
  // we now have a reference to bar
}

void bar() { }

int main()
{
    foo(bar);
}

我们什么时候关心防止指针衰减的功能?我问这个有用的时间,而不是为什么它不被禁止。

2 个答案:

答案 0 :(得分:3)

与对象一样,如果“没有对象”(“无功能”)是一个合理的值,我们指向一个指针,如果我们希望确保(除非有人坚持用脚射击自己),总会有一个参考一个有效的对象(函数)引用。

考虑以下穷人的功能包装(富人去over there)。

template<typename>
class Function;  // never defined

template<typename ReturnT, typename... ArgT>
class Function<ReturnT(ArgT...)>
{

private:

  ReturnT (*func_)(ArgT...);

public:

  // Will also accept a 'nullptr'
  Function(ReturnT (*func)(ArgT...)) noexcept : func_ {func}
  {
  }

  ReturnT
  operator()(ArgT... args)
  {
    return this->func_(args...);
  }
};

现在我们可以编写以下程序,该程序运行正常。

#include <iostream>

int
add(int a, int b)
{
  return a + b;
}

int
main()
{
  Function<int(int, int)> f {add};    // ok
  std::cout << f(5, 7) << std::endl;  // ok, prints 12
}

但是,我们也可以编写以下程序,但该程序并不好用。

int
main()
{
  Function<int(int, int)> f {nullptr};  // compiles fine
  std::cout << f(5, 7) << std::endl;    // compiles fine, crashes at run-time
}

相反,如果我们在模板的定义中将(*func)替换为(&func)

// Won't accept a 'nullptr'
Function(ReturnT (&func)(ArgT...)) noexcept : func_ {func}
{
}

Function<int(int, int)> f {nullptr};  // compile-time error

会触发编译时错误。

答案 1 :(得分:0)

对我而言,区别在于普通变量引用和指针之间。参考文献比指针更好处理。

当我自定义算法的某些部分时,我有一个用例。它有一些阶段,我可以在每个阶段的几个选项之间切换。这当然可以用指针实现,但是嘿,你可以在任何地方使用指针代替引用。

看起来与此相似:

#include <iostream>
using namespace std;

    class Foo
    {
    public:
      Foo(void(&t)()) : barish(t)  {  };
      void fun() {barish();};
    private:
      void(&barish)();
    };


void bar() { cout << "meow\n";}
void bark() { cout << "woof\n";}

int main()
{
    Foo foo1(bar);
    Foo foo2(bark);

    foo1.fun();
    foo2.fun();
}

您可以自定义fun并且不必处理解除引用并断言它不为空。