2011-01-07 2 views
13

C++ вопрос,Что ИНТ и среднее

Я знаю

int* foo(void) 

Foo возвращает указатель целого типа

как о

int &foo(void) 

, что делает его возвращение ?

Большое спасибо!

+0

Также знакомьтесь: http://stackoverflow.com/questions/2139224/how-to-pass-objects-to-functions-in-c –

ответ

1

Он возвращает ссылку на переменную int.

+0

Не нужно быть переменной (это означает, что она названа) , Он возвращает ссылку на объект int. –

27

Он возвращает ссылку на инт. Ссылки похожи на указатели, но с некоторыми важными отличиями. Я бы рекомендовал вам ознакомиться с различиями между указателями, ссылками, объектами и примитивными типами данных.

«Эффективный C++» и «Более эффективный C++» (оба Скотта Мейерса) имеют несколько хороших описаний различий и когда использовать указатели и ссылки.

EDIT: Есть несколько ответов, говорящих по строкам «ссылки - это просто синтаксический сахар для упрощения обработки указателей». Они, безусловно, не.

Рассмотрим следующий код:

int a = 3; 
int b = 4; 
int* pointerToA = &a; 
int* pointerToB = &b; 
int* p = pointerToA; 
p = pointerToB; 
printf("%d %d %d\n", a, b, *p); // Prints 3 4 4 
int& referenceToA = a; 
int& referenceToB = b; 
int& r = referenceToA; 
r = referenceToB; 
printf("%d %d %d\n", a, b, r); // Prints 4 4 4 

Линия p = pointerToB изменяет значение p, т.е. он теперь указывает на другой кусок памяти.

r = referenceToB делает что-то совершенно другое: оно присваивает значение b, где раньше было значение a. Это не изменить r на всех. r по-прежнему относится к одной и той же части памяти.

Разница тонкая, но очень важная.

Если вы все еще считаете, что ссылки - это просто синтаксический сахар для обработки указателя, то , пожалуйста, читайте книги Скотта Мейерса. Он может объяснить разницу намного лучше, чем я могу.

+1

+1 для книг Скотта Мейерса. Должен быть у всех, кто хочет хорошо понимать C++. – Matthieu

+1

Да, они оба отличные книги. Преподавал мне все, что знаю! –

+0

Таким образом, ссылочные переменные являются альтернативным синтаксисом для указателей * const *. – Bento

0

Этот вопрос вообще не является C/C++, так как C не имеет ссылок, только указатели. Int & - это ссылка на int. Кроме того, вам не нужно void, это может быть просто int& foo();

+0

Это то, что в документе говорится о встроенном компиляторе TMS320C28x C/C++ в техасском инструменте, http://focus.ti.com/lit/ug/spru514c/spru514c.pdf, стр. 122, int & __ byte (int, unsigned int), я думаю, это отличается от ПК –

+0

@Alfred: Нет, не совсем. Языки C и C++ не имеют специальных встроенных версий. Руководство неверно, и это в значительной степени. – Puppy

+0

@ Альфред Чжун. Никакая документация не говорит так же, как и все остальные здесь. –

0

просто играть с переменными, чтобы показать вам смысл

int i = 5; 
int * pI = &i; 
int & referenceToI = * pI; 
referenceToI = 4; // now i == 4 

EDIT: Ссылки лишь синтаксический сахар для облегчения обработки указателей. на уровне сборки код, сгенерированный компилятором, возвращает вам адрес-указатель

+0

Спасибо! Я знаю это. Что меня смущает, когда оно используется в объявлении функции, например int & foo (...), что возвращает функция? –

+0

Возвращает ссылку на то, что вы положили после 'return'. –

+0

Нет возврата, я думаю, что в нем есть язык ассемблера, массив MOVB [byte_index] .LSB, src, я понятия не имею, что это значит. –

3

Будьте осторожны ... вы идете по линии C/C++.Существует довольно четкое различие, но это не всегда выглядит так:

C++: это часто означает ссылку. Например, рассмотрим:

void func(int &x) 
{ 
    x = 4; 
} 

void callfunc() 
{ 
    int x = 7; 
    func(x); 
} 

Таким образом, C++ можно передать по значению или pass by reference.

C однако не имеет такого прохода по ссылочной функциональности. & означает «addressof» и является способом формулировки указателя из переменной. Однако учтите следующее:

void func(int* x) 
{ 
    *x = 4; 
} 

void callfunc() 
{ 
    int x = 7; 
    func(&x); 
} 

Обманчиво похожий, но принципиально иной. То, что вы делаете в C, передает раз. Скопировать код с указателем. Теперь эти вещи все еще указывают на одну и ту же область памяти, поэтому эффект похож на проход по ссылке в терминах направленной памяти, но это не ссылочная информация. Это ссылка на точку в памяти.

Попробуйте это (Compile, как C):

#include <stdio.h> 

void addptr(int* x) 
{ 
    printf("Add-ptr scope 1:\n"); 
    printf("Addr: %p\n", x); 
    printf("Pointed-to-memory: %d\n", *x); 
    *x = *x + 7; 
    x++; 
    printf("Add-ptr scope 2:\n"); 
    printf("Addr: %p\n", x); 
    printf("Pointed-to-memory: %d\n", *x); 
} 

int main(int argc, char** argv) 
{ 
    int a = 7; 
    int *y = &a; 
    printf("Main-Scope 2:\n"); 
    printf("Addr: %p\n", y); 
    printf("Pointed-to-memory: %d\n", *y); 
    addptr(y); 
    printf("Main-Scope 2:\n"); 
    printf("Addr: %p\n", y); 
    printf("Pointed-to-memory: %d\n", *y); 
    return 0; 

} 

Если С было пройти по ссылке, входящий указатель адрес, когда изменен addptr должен быть отражен в main, но это не так. Указатели по-прежнему являются значениями.

Итак, Cнет есть какой-либо проход по ссылке. В C++ это существует, и это то, что & означает в аргументах функции и т. Д.

Редактировать: Возможно, вам интересно, почему я не могу сделать эту демонстрацию на C++ легко. Это потому, что я не могу изменить адрес ссылки. Вообще. С т his quite good guide to references:

How can you reseat a reference to make it refer to a different object?

No way.

You can't separate the reference from the referent.

Unlike a pointer, once a reference is bound to an object, it can not be "reseated" to another object. The reference itself isn't an object (it has no identity; taking the address of a reference gives you the address of the referent; remember: the reference is its referent).

In that sense, a reference is similar to a const pointer such as int* const p (as opposed to a pointer to const such as int const* p). But please don't confuse references with pointers; they're very different from the programmer's standpoint.

По просьбе о возвращении ссылки:

#include <iostream> 

using namespace std; 

int& function(int f) 
{ 
    f=f+3; 
    return f; 
} 

int main(int argc, char** argv) 
{ 
    int x = 7; 
    int y; 
    y = function(x); 
    cout << "Input: " << x << endl; 
    cout << "Output:" << y << endl; 
    return 0; 
} 

Любой хороший компилятор должен дать вам это предупреждение в той или иной форме:

exp.cpp: 7: 11 : предупреждение: ссылка на стеке памяти, связанной с локальной переменной 'f', возвращенный

Что это значит? Ну, мы знаем, что аргументы функции вставляются в стек (обратите внимание: на самом деле не на x64, они попадают в регистры, а затем в стек, но они находятся в стеке буквально на x86), и что это предупреждение говорит о том, что создание ссылки на такие объект не является хорошей идеей, потому что его не гарантируют, что он останется на месте. Дело в том, что это просто удача.

Итак, что дает? Попробуйте эту измененную версию:

#include <iostream> 

using namespace std; 

int& function(int& f) 
{ 
    f=f+3; 
    return f; 
} 

int main(int argc, char** argv) 
{ 
    int x = 7; 
    int y; 
    y = function(x); 
    cout << "Input: " << x << endl; 
    cout << "Output:" << y << endl; 
    return 0; 
} 

Запустите это, и вы увидите, что оба значения обновляются. Какие? Ну, они оба относятся к одной и той же вещи, и эта вещь редактируется.

+1

Большое спасибо! Я знаю, что в C & foo, и если foo является int, это будет адрес foo и может быть передан int * type. Я смущен, когда он используется в объявлении функции, int & foo (...), что это не значит? –

+0

«То, что вы делаете на C, передает копию указателя». Нет, вы не являетесь - вы передаете * значение * * адреса * локальной переменной 'x' в' func' в качестве аргумента * указателя *. На этом этапе нет других указателей, поэтому вы не можете их копировать. В примере на C++ вы передаете переменную 'x' функции, которая принимает аргумент * reference *, поэтому вы получаете ссылку на' x'. Их реализация (возможно) одинакова: адрес 'x' попадает в стек. IOW C * does * позволяет использовать ссылочную семантику, но не поддерживает синтаксис для их поддержки. – dajames

+0

Да, вы передаете * копию * значения указателя - * копию указателя *. Указатель - это адрес памяти сам по себе (поэтому «переменная»), содержащая другой адрес памяти. Прикрепите 'gdb' к процессу, и вы сможете это увидеть. Поэтому акт копирования - это назначить новое пространство памяти и ввести значение. Это то, что передается по значению. –

1

Из комментариев Альфреда

This is what the document says, Texas instrument's TMS320C28x C/C++ compiler intrinsics , page 122, int&__byte(int, unsigned int), I guess it is different from PC – Alfred Zhong

Из инструкции:

int &__byte(int *array, unsigned int byte_index);

MOVB array[byte_index].LSB, src

The lowest adressable unit in C28x is 16 bits. Therefore, normally you cannot access 8-bit MOVB dst, array[byte_index]. LSB entities off a memory location. This intrinsic helps access an 8-bit quantity off a memory location, and can be invoked as follows:

__byte(array,5) = 10;
b = __byte(array,20);

Это просто означает, что функция возвращает ссылку на целое число, которое действует как количество 8 бит. Поскольку значение является модификацией ссылки, будет изменен объект в команде назначения (точно так же как MOVB), тогда как присвоение b будет копировать (точно так же, как MOVB) в пункт назначения.

+0

Спасибо, Мартин, я смущен, потому что я сделал то же, что и в руководстве: __byte (array, 5) = 10, а компилятор продолжает жаловаться на ошибку: выражение должно быть модифицируемым значением lvalue " –