Форум программистов, компьютерный форум CyberForum.ru

Ссылки и указатели - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 102, средняя оценка - 4.97
xKirillx
0 / 0 / 0
Регистрация: 01.03.2011
Сообщений: 11
01.03.2011, 12:10     Ссылки и указатели #1
Добрый день.
Возможно было. В чем существенная разница между передачей данных в функцию по ссылке или указателю. В каких случаях вы бы что рекоммендовали. Заранее спасибо.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
01.03.2011, 12:10     Ссылки и указатели
Посмотрите здесь:

C++ Указатели и ссылки
C++ [C++]Ссылки и указатели?
C++ Указатели и ссылки [С++]
Указатели и Ссылки C++
C++ Указатели и ссылки
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.07.2011, 18:21     Ссылки и указатели #41
Цитата Сообщение от kravam Посмотреть сообщение
компилится, шеф
Не должно! Какой компилятор? Выкиньте его на свалку, он нарушает стандарт.
С преобразованием типа - будет компилиться, без преобразования - не должно.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
15.07.2011, 18:36     Ссылки и указатели #42
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Не должно! Какой компилятор? Выкиньте его на свалку, он нарушает стандарт
gcc в режиме Си вроде бы как сожрёт это дело
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.07.2011, 18:41     Ссылки и указатели #43
Насколько помню, в Си не было ссылок...
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
15.07.2011, 18:44     Ссылки и указатели #44
ДРузья, я был неправ. Но это бросает тень на меня и только.

Итак, мне нравится когда всё о чём я говорил компилится с преобразованием типов
C++
1
        p=(void(*)())&f;
Это плохо.
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
15.07.2011, 18:46     Ссылки и указатели #45
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Насколько помню, в Си не было ссылок...
А при чём тут ссылки? Речь идёт о преобразовании типа над указателями на функцию (первый пример из поста #22). Далее в посте #38 я нарисовал пример, отрезавшись от Си++ (чтобы его можно было компилять и на Си, и на Си++). В режиме Си на, к примеру, борландовском компиляторе он не пройдёт компиляцию, а на gcc - пройдёт. Ибо gcc по умолчанию работает в некотором своём расширении, который допускает больше безобразия, нежели стандартный Си
grizlik78
15.07.2011, 18:47
  #46

Не по теме:

— Доктор, когда я делаю вот так, мне больно!
— А вы не делайте "вот так"!

ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.07.2011, 18:48     Ссылки и указатели #47
Цитата Сообщение от kravam Посмотреть сообщение
ДРузья, я был неправ. Но это бросает тень на меня и только.

Итак, мне нравится когда всё о чём я говорил компилится с преобразованием типов
C++
1
        p=(void(*)())&f;
Это плохо.
Не... Просто аккуратно надо.
Я когда-то исследовал функции с переменным числом параметров и тоже вовсю использовал преобразование указателей. Было интересно передать в функцию с переменным числом параметров указатели на функции с разным числом параметров и там все их вызвать...
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
15.07.2011, 19:14     Ссылки и указатели #48
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Я когда-то исследовал функции с переменным числом параметров и тоже вовсю использовал преобразование указателей. Было интересно передать в функцию с переменным числом параметров указатели на функции с разным числом параметров и там все их вызвать...
С точки зрения языка сие допустимо, но по сути дела это UB, потому как в точке вызова и в точке самой функции должны быть одинаковые прототипы. Возьмём пример из двух файлов:

C
1
2
3
4
5
6
7
8
extern void func (float f1, float f2);
 
int
main (void)
{
  func (1.25, 2.75);
  return 0;
}
C
1
2
3
4
5
6
7
#include <stdio.h>
 
void
func (int f1, int f2)
{
  printf ("f1=%x, f2=%x\n", f1, f2);
}
Мы видим, что в точке вызова прототип описан как с двумя float'ами, а в точке реализации - с двумя int'ами. Два файла компилируются раздельно, а потому для компилятора они оба корректные. Линкер работает только с именами: он видит, что в одном модуле есть определение символа "func", а в другом - использование символа с таким же именем, а потому он свяжет эти две точки и всё. Такой код будет работать. При исполнении он выдаст:

Код
f1=3fa00000, f2=40300000
В точке вызова компилятор передаст параметры, которые есть наборы битов для представления констант 1.25 и 2.75 как float. А а в самой функции из этого же места прочтутся эти же самые наборы битов, но будут трактоваться как int'ы (от чего и напечатаны такие значения). Казалось бы, что поведение программы всё равно оказывается детерминированным. А на самом деле это не так. В случае i386 при передаче целых и плавающих значений используются одни и те же программные соглашения. В нашем случае размер int'а совпадает с размером float'а, а потому место, через которое передаются параметры (видимо это стек) совпадёт с местом, откуда они читаются. На архитектуре sparc v9 программные соглашения устроены таким образом, что для целых и плавающих значений используются разные правила передачи параметров. В этом случае параметры типа float передадутся на плавающих регистрах, а параметры типа int будут прочитаны с целочисленных регистров (и окажутся неинициализированными).

Ровно такая же бодяга происходит и при преобразовании типов над указателями на функции. Т.е. компилятор такую операцию разрешает, но всю ответственность перекладывает на программиста. Если программист даёт себе отчёт в том, что данная программа предназначена для конкретных программных соглашений по передаче параметров, то у него всё будет работать. Если программист считает, что если на одной архитектуре у него отработало, а значит будет работать везде - то сам дурак

Ну и такие же риски имеются, если с var_arg'ами работать так, как в начальных примерах твоей статьи - непосредственно через указатели

Добавлено через 1 минуту
Да, забыл сказать. Это пример работает только в Си, потому как с точки зрения Си++ функции с одним именем, но разными типами параметров - это разные функции
silentnuke
Android Programmer
137 / 138 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 23:13     Ссылки и указатели #49
такс всеравно не до конца пока улавливаю суть.
с указателем то ещё ладно, но для статической переменной откуда память то берется?
Закинул все это дело в вечный цикл, подождал минут в 20 в надежде что оно вылетит, но нет..
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>
using namespace std;
 
class B
{
public:
    int* a;
    int b;
    void func2()
    {
        a=new int;
        *a=10;
        b=250;
        cout<<*a<<" "<<b<<endl;
    }
};
 
int main ()
{
    while(1)
    {
        B *p;
        p->func2();
        *p->a=2222;
        p->b=20;
        cout<<*p->a<<" "<<p->b<<endl;
    }
    return 0;
}
OstapBender
 Аватар для OstapBender
581 / 519 / 35
Регистрация: 22.03.2011
Сообщений: 1,585
15.07.2011, 23:37     Ссылки и указатели #50
Цитата Сообщение от silentnuke Посмотреть сообщение
B *p; p->func2(); *p->a=2222;
так ваще делать нельзя.

по идее должно вылететь.

побольше выделять попробуй:
C++
1
2
3
4
5
    int counter=0;
    while (1) {
        int* p = new int[40000];
        std::cout << "ok: " << ++counter << '\n';
    }
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
15.07.2011, 23:40     Ссылки и указатели #51
Цитата Сообщение от silentnuke Посмотреть сообщение
такс всеравно не до конца пока улавливаю суть.
с указателем то ещё ладно, но для статической переменной откуда память то берется?
Закинул все это дело в вечный цикл, подождал минут в 20 в надежде что оно вылетит, но нет..
Все переменные С++ распределяются на три вида по виду памяти:
static storage (глобальные и статические переменные), automatic storage (локальные перменные) и dynamic storage (динамические переменные). Для статических-глобальных объектов память рампределяет компилятор при трансляции. Они "живут" все время, пока работает программа. Локальные объекты "рождаются" в стеке, там же и "помирают" во время работы программы. А динамические объекты создаются явно во время работы программы в куче. И их надо явно "убивать".
Поскольку куча - 2 гига (виртуальная память), то выделяя по одному int, вы нескоро ее исчерпаете.
silentnuke
Android Programmer
137 / 138 / 5
Регистрация: 08.12.2010
Сообщений: 421
15.07.2011, 23:54     Ссылки и указатели #52
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
Все переменные С++ распределяются на три вида по виду памяти:
static storage (глобальные и статические переменные), automatic storage (локальные перменные) и dynamic storage (динамические переменные). Для статических-глобальных объектов память рампределяет компилятор при трансляции. Они "живут" все время, пока работает программа. Локальные объекты "рождаются" в стеке, там же и "помирают" во время работы программы. А динамические объекты создаются явно во время работы программы в куче. И их надо явно "убивать".
Поскольку куча - 2 гига (виртуальная память), то выделяя по одному int, вы нескоро ее исчерпаете.
я ж говорю я пока не понимаю откуда память для переменной b берется, ведь как я понимаю, она должна выделяться при создании объекта, а объект то не создается, или я что-то не так понимаю?
ValeryLaptev
Эксперт C++
1005 / 784 / 46
Регистрация: 30.04.2011
Сообщений: 1,595
16.07.2011, 00:01     Ссылки и указатели #53
Цитата Сообщение от silentnuke Посмотреть сообщение
я ж говорю я пока не понимаю откуда память для переменной b берется, ведь как я понимаю, она должна выделяться при создании объекта, а объект то не создается, или я что-то не так понимаю?
VS 2008 в отладочном режиме тут же выдала
Run-Time Check Failure #3 - The variable 'p' is being used without being initialized.
То есть, у тебя указатель не инициализирован, а ты пытаешься вызвать метод через него.
schdub
 Аватар для schdub
2902 / 1246 / 222
Регистрация: 19.01.2009
Сообщений: 3,214
Завершенные тесты: 1
16.07.2011, 00:02     Ссылки и указатели #54
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
динамические объекты создаются явно во время работы программы в куче
Если имеются ввиду операторы new/delete, то у Herb Sutter применяется термин "Free Store", а не "Heap".

Exceptional C++ - Memory Management - Part I
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
16.07.2011, 00:08     Ссылки и указатели
Еще ссылки по теме:

Ссылки и указатели C++
Указатели и ссылки C++
Указатели и ссылки C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16825 / 5246 / 321
Регистрация: 30.03.2009
Сообщений: 14,127
Записей в блоге: 26
16.07.2011, 00:08     Ссылки и указатели #55
Цитата Сообщение от silentnuke Посмотреть сообщение
я ж говорю я пока не понимаю откуда память для переменной b берется, ведь как я понимаю, она должна выделяться при создании объекта, а объект то не создается, или я что-то не так понимаю?
Указатель p не инициализировался, а потому там мусорное значение. Звёзды встали так, что этот мусор оказался валидным адресом. И по этому адресу обращение не сломалось, при этом ты записывал в поле a, а потому просто гадил в чью-то память. Опять-таки звёзды встали так, что это оказалось нефатальным.

То, что у тебя цикл бесконечный - по сути ничего не означает. Каждый раз переменная p у тебя лежала в одном и том же месте стека, а потому каждый раз в ней был записан один и тот же мусор. А следовательно ты каждый раз гадил в одну и ту же память. Т.е. что цикл из одной итерации, что из бесконечного количества - в данном случае роли не играет

Добавлено через 2 минуты
Цитата Сообщение от ValeryLaptev Посмотреть сообщение
То есть, у тебя указатель не инициализирован, а ты пытаешься вызвать метод через него
Конкретное значение указателя роли не играет, ибо на вызове метода это никак не отражается (см. по ссылкам из поста #24). Реальная засада могла быть только при записи в поля a и b. Но, как уже писал выше, звёзды встали так, что мусорное значение оказалось валидным адресом, нагадив по которому ничего страшного не произошло
Yandex
Объявления
16.07.2011, 00:08     Ссылки и указатели
Ответ Создать тему
Опции темы

Текущее время: 18:45. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru