2015-05-31 3 views
3

В этом примере код func1 является типом void (*)(int, double) и funky является типом void(&)(int, double).Разница между void (*)() и void (&)() в C++

#include <iostream> 

using namespace std; 

void someFunc(int i, double j) { 
    cout << i << ":" << j << endl; 
} 

int main(int argc, char *argv[]) { 

    auto func1 = someFunc; 
    auto& func2 = someFunc; 

    cout << typeid(func1).name() << endl; 
    cout << typeid(func2).name() << endl; 

    func1(10, 20.0); 
    func2(10, 30.0); 
} 

Выход показывает разницу:

PFvidE 
FvidE 
10:20 
10:30 

Практически чем разница между этими двумя типами?

+0

Внутренние представления одинаковы, но значения уровня языка совершенно разные. – texasbruce

+0

«Язык синтаксического сахара» языка позволяет использовать их с идентичным синтаксисом. Но семантически они разные. Например, 'auto & func2 = & someFunc;' не будет компилироваться, а 'auto func1 = & someFunc;' будет. Хотя использование 'auto' в этом контексте будет только запутывать разницу. – AnT

ответ

4

Если вы хотите иметь возможность назначить указатель на функцию, а затем изменить то, на что указывает этот указатель, используйте auto fp = func. Если нет, то используйте ссылку auto& rp = func, так как вы не можете переназначить его:

#include <iostream> 
using namespace std; 

int funcA(int i, int j) { 
    return i+j; 
} 

int funcB(int i, int j) { 
    return i*j; 
} 

int main(int argc, char *argv[]) { 
    auto fp = funcA; 
    auto& rp = funcA; 

    cout << fp(1, 2) << endl; // 3 (1 + 2) 
    cout << rp(1, 2) << endl; // 3 (1 + 2) 

    fp = funcB; 
    //rp = funcB; // error: assignment of read-only reference 'rp' 

    cout << fp(1, 2) << endl; // 2 (1 * 2) 

    return 0; 
} 

Я пытался придумать более практический пример того, почему кто-то когда-нибудь сделать это, ниже код, который использует массив указателей вызова функции на основе пользовательского ввода (любой элемент arr также может быть изменен во время выполнения, чтобы указать на другую функцию):

#include <iostream> 
using namespace std; 

void funcA(int i, int j) { 
    std::cout << "0: " << i << ", " << j << endl; 
} 

void funcB(int i, int j) { 
    std::cout << "1: " << i << ", " << j << endl; 
} 

void funcC(int i, int j) { 
    std::cout << "2: " << i << ", " << j << endl; 
} 

int main(int argc, char *argv[]) { 
    if (argc < 2) { 
     cout << "Usage: ./a.out <val>" << endl; 
     exit(0); 
    } 

    int index = atoi(argv[1]); 
    if (index < 0 || index > 2) { 
     cout << "Out of bounds" << endl; 
     exit(0); 
    } 

    void(* arr[])(int, int) = { funcA, funcB, funcC }; 
    arr[index](1, 2); 

    return 0; 
} 
0
auto func1 = someFunc; 
auto& func2 = someFunc; 

Скажем у вас есть еще одна функция, и вы хотите func2 указать эту другую функцию

void function() 
{ 
    cout<<"Hello world"<<endl; 
} 

Так вы ниже

func2 = function(); 

Все вы получите ошибку компиляции. Причина func2 является ссылкой и после инициализации ссылки ее нельзя изменить.

Смежные вопросы