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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
#1

Передача параметра по ссылке - C++

13.09.2012, 13:51. Просмотров 831. Ответов 3
Метки нет (Все метки)

Всем здравствуйте. Други, помогите разобраться.
Сидю вникаю в работу указателей и памяти, паралельно пытаюсь написать велосипед, в виде контейнера аля вектор. После хочу сваять из него темплейт и перегрузить оператор [] и т.п. , а пока он имеет такой вид, как я представил. Вот примерная схема организации данных:

Передача параметра по ссылке


Здесь класс MsqArr имеет поле MsqData* dataPtr - массив указателей на структуры, которые содержат число - индекс, и указатель на данные, позже все действия по сортировке и перестановке будут производиться с массивом указателей на структуры.

Так вот вопрос, ниже в коде, в методе:
MsqArr::insert(const int idx, const int &val)

- если передать параметр val не по ссылке, а по значению:
MsqArr::insert(const int idx, const int val)

то после, когда я вызываю этот метод сколько то раз, что бы задать пары индекс - значение, и вывожу на экран... Вуаля - все элементы почему - то имеют одно и тоже значение - то которое передавалось последнему вызову, хотя значения индексов имеют нужные значения. Не подскажите почему?

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <iostream>
 
using namespace std;
 
///////////////////////////////////////////////////////////
struct MsqData {
    int index;
    const int* data;
};
///////////////////////////////////////////////////////////
class MsqArr {
 
    public :
 
        MsqArr() :
            length (0),
            dataPtr(NULL)
        {}
 
        ~MsqArr()
        {
            delete [] this->dataPtr;
        }
        // Вот сдесь если второй параметр передавать не по ссылке
        // то все элементы будут иметь одно и то же значение - последнее.
        // @param int idx - индекс элемента
        // @param int val - значение элемента
        bool insert(const int idx, const int val)
        {
            MsqData *ptrArr = new MsqData[this->length + 1];
 
            for (int i = 0; i < this->length; i++) {
                *(ptrArr + i) = *(this->dataPtr + i);
                delete (this->dataPtr + i);
            }
 
            this->dataPtr = ptrArr;
 
            (this->dataPtr + this->length)->index = idx;
            (this->dataPtr + this->length)->data  =& val;
 
            this->length++;
            return true;
        }
 
        friend ostream& operator << (ostream& out, MsqArr& arr)
        {
            cout << "Array(" << endl;
            for (int i = 0; i < arr.length; i++) {
                cout << "\t[" << (arr.dataPtr + i)->index << "] => "
                     << *((arr.dataPtr + i)->data) << endl;
            }
            cout << ")" << endl;
            return out;
        }
 
    protected :
        int length;
        MsqData* dataPtr;
};
///////////////////////////////////////////////////////////
int main()
{
    MsqArr arr1;
 
    try {
 
        arr1.insert(0, 111);
        arr1.insert(1, 222);
        arr1.insert(2, 333);
        arr1.insert(3, 444);
 
    } catch (bad_alloc) {
        cout << "Bad allocation memory!" << endl;
    }
 
    cout << arr1 << endl;
 
    return 0;
}
ЗЫ: Я конечно понимаю, что, передав параметр по значению, переменная val - в методе становится локальной и погибает по окончанию работы с методом, а указатель (this->dataPtr + ... )->data указывает хрензнаеткуда, но почему в итоге вывод имеет следующий вид:

// если передавать НЕ по ссылке то таким (парадокс):
Array(
[0] => 444
[1] => 444
[2] => 444
[3] => 444
)

// если передавть параметр по ссылке, то вывод проги будет следующим (то что нужно):
Array(
[0] => 111
[1] => 222
[2] => 333
[3] => 444
)
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.09.2012, 13:51
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Передача параметра по ссылке (C++):

Передача параметра по ссылке - C++
Всем доброго времени суток. Понимаю что вопрос покажется очень глупым, но я уже несколько часов бьюсь и не могу решить эту элементарную...

Передача параметра по ссылке - C++
Здравствуйте! Подскажите пожалуйста! Делаю пример из книги: #include &lt;iostream&gt; #include &lt;conio.h&gt; using namespace...

Передача параметра по константной ссылке - что это? - C++
объясните мне пожалуйста что такое передача параметра в функцию по константной ссылке? я просто вообще не могу представить что значит &amp; в...

Как получить адрес параметра, передоваемого по ссылке? - C++
подскажите как получить адрес параметра, передоваемого по ссылке? void f(int &amp;a...) { int *p = ????; for(int i = 0; i &lt; 3;...

Передача по ссылке - C++
С помощью функции rand() округлить значение double и передать его по ссылке.

Передача по ссылке - C++
Здравствуйте. 1.typedef struct { MATRIXX_LENTA&lt;double&gt;* MATR; //Ленточная матрица } DATA_LENTA, *PDATA_LENTA; DWORD WINAPI...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
I.M.
564 / 547 / 5
Регистрация: 16.12.2011
Сообщений: 1,389
13.09.2012, 14:08 #2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 bool insert(const int idx, const int val)
        {
            MsqData *ptrArr = new MsqData[length + 1];
 
            for (int i = 0; i < length; i++) {
                *(ptrArr + i) = *(this->dataPtr + i);
                //delete (this->dataPtr + i);//с этим у меня не работало
            }
            if(dataPtr)delete[] dataPtr;
            this->dataPtr = ptrArr;
 
            (this->dataPtr + this->length)->index = idx;
            (this->dataPtr + this->length)->data  = new int(val);
 
            this->length++;
            return true;
        }
И зачем везде this? так обычно не пишут... вам компилятор не жалуется на old-style?

Добавлено через 6 минут
Цитата Сообщение от moskitos80 Посмотреть сообщение
Вуаля - все элементы почему - то имеют одно и тоже значение
Я так понимаю, они пушаются в стек на одно и то же место. Попробуйте сделать cout << &val и увидите, что адрес один и тот же
1
Герц
524 / 341 / 4
Регистрация: 05.11.2010
Сообщений: 1,077
Записей в блоге: 1
13.09.2012, 14:09 #3
Почему это не пишут? Пишут.
Нужно же различать в коде поля класса и прочие переменные, вот и пишут везде this->field.
Хотя лучше давать полям какой-нибудь префикс, например 'mField' или 'm_field'
1
moskitos80
61 / 61 / 10
Регистрация: 04.10.2011
Сообщений: 217
Завершенные тесты: 1
13.09.2012, 17:20  [ТС] #4
Цитата Сообщение от Герц Посмотреть сообщение
Нужно же различать в коде поля класса и прочие переменные
Именно по этой причине всегда пишу this->...

Цитата Сообщение от I.M. Посмотреть сообщение
(this->dataPtr + this->length)->data *= new int(val);
!!! Вот спасибо добрый человече! Теперь, кстати я могу передавать в метод константы.

Добавлено через 46 минут
Посмотрите пожалуйста, что у меня в результате получилось... как вы думаете это полное убожество или более - менее нормальная реализация? Если можно укажите пожалуйста мои ошибки. Я С++ изучаю около 3 месяцев, самостоятельно, по книге Р.Лафоре: "ООП в С++" хотелось бы знать мнение сведущего человека:

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <iostream>
#include <string>
 
using namespace std;
 
namespace msq {
///////////////////////////////////////////////////////////
template<class Type>
struct MsqData {
    int index;
    Type* data;
};
///////////////////////////////////////////////////////////
template<class Type>
class Array {
 
    public :
        Array() :
            length (0),
            dataPtr(NULL)
        {/*empty*/}
 
        ~Array()
        {
            delete [] this->dataPtr;// В АД!
        }
        /** Создать элемент под индексом idx со значением val
         * @param const int idx - индекс элемента
         * @param const int val - значение элемента
         * @return void
         */
        void set(const int idx, const Type &val)
        {
            // Если такой индекс у нас уже существует,
            // Мы просто перезапишем его значение:
            if (this->isset(idx)) {
                (this->dataPtr + idx)->index = idx;
                (this->dataPtr + idx)->data  = new Type(val);
                return;
            }
            // Создаём новый массив кол-вом элементов на 1
            // больше существующего this->dataPtr, что бы
            // поместить туды новый элемент:
            MsqData<Type> *ptrArr = new MsqData<Type>[this->length + 1];
            // Перегоняем указатели в новый массив
            // после цикла у нас останется не заполненным
            // последний элемент:
            for (int i = 0; i < this->length; i++) {
                *(ptrArr + i) = *(this->dataPtr + i);
                delete (this->dataPtr + i);
            }
            // Меняем назначение указателя на массив новой
            // размерности:
            this->dataPtr = ptrArr;
            // Заполняем последний элемент новым значениями
            (this->dataPtr + this->length)->index = idx;
            (this->dataPtr + this->length)->data  = new Type(val);
            // Инкрементируем длину нашего массива
            this->length++;
            return;
        }
        /** Получить элемент под индексом idx
         *  если такого элемента не существует вернёт 0
         * @param const int idx - индекс элемента
         * @return int&
         */
        Type& get(int idx)
        {
            // Если такой индекс есть - возвращаем значение
            // Здесь не получается сделать так:
            // if (this->isset(idx)) . . .
            // потому что Array::isset(int idx) - вернет тип bool
            for (int i = 0; i < this->length; i++) {
                if ( (this->dataPtr + i)->index == idx ) {
                    return *(this->dataPtr + i)->data;
                }
            }
            // Если нет возвращаем тип инициализированный нулём
            return *(new Type);
        }
        /** Проверить, существует ли элемент под индексом idx
         *  если такого элемента не существует вернёт false
         * @param const int idx - индекс элемента
         * @return bool
         */
        bool isset(const int idx)
        {
            for (int i = 0; i < this->length; i++) {
                if ( (this->dataPtr + i)->index == idx ) {
                    return true;
                }
            }
            return false;
        }
 
        Type& operator [] (const int idx)
        {
            // Если такого индекса не существует...
            if (!this->isset(idx)) {
                // Заводим его с пустым значением
                this->set(idx, *(new Type));
            }
            return this->get(idx);
        }
 
        friend ostream& operator << (ostream& out, Array<Type>& arr)
        {
            cout << "Array(" << endl;
            for (int i = 0; i < arr.length; i++) {
                cout << "\t["  << (arr.dataPtr + i)->index << "] => "
                     << arr[i] << endl;
            }
            cout << ")" << endl;
            return out;
        }
 
    protected :
        // Длина массива
        int length;
        // Массив указателей на структуры с индексами и указателями
        MsqData<Type>* dataPtr;
};
///////////////////////////////////////////////////////////
} // END namespace msq
 
int main()
{
    // TESTING:
    
    msq::Array<int>    intArray;
    msq::Array<string> stringArray;
    msq::Array<double> doubleArray;
 
    cout << "----------------- INT --------------" << endl;
 
    intArray[0] = 555;
    intArray[1] = 777;
 
    cout << intArray << endl;
    cout << "intArray[0]  = " << intArray[0]  << endl;
    cout << "intArray[1]  = " << intArray[1]  << endl;
    cout << "intArray[50] = " << intArray[50] << endl;// Не существующий!
 
    cout << "-------------------------------------" << endl;
 
    cout << "---------------- DOUBLE -------------" << endl;
 
    doubleArray[0] = 111.5;
    doubleArray[1] = 222.5;
 
    cout << doubleArray << endl;
    cout << "doubleArray[0]  = " << doubleArray[0]  << endl;
    cout << "doubleArray[1]  = " << doubleArray[1]  << endl;
    cout << "doubleArray[50] = " << doubleArray[50] << endl;// Не существующий!
 
    cout << "-------------------------------------" << endl;
 
    cout << "---------------- STRING -------------" << endl;
 
    stringArray[0] = "one";
    stringArray[1] = "two";
 
    cout << stringArray << endl;
    cout << "stringArray[0]  = " << stringArray[0]  << endl;
    cout << "stringArray[1]  = " << stringArray[1]  << endl;
    cout << "stringArray[50] = " << stringArray[50] << endl;// Не существующий!
 
    cout << "-------------------------------------" << endl;
 
    return 0;
}
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.09.2012, 17:20
Привет! Вот еще темы с ответами:

Передача по ссылке - C++
В учебнике написано, что можно использовать функцию с левой стороны операции присваивания, если она возвращает ссылку. Например, так: ...

Передача auto_ptr по ссылке - C++
Передача auto_ptr по ссылке противоречит концепции владения. Нельзя быть полностью уверенным в том, что функция, получающая auto_ptr по...

Передача значения по ссылке - C++
1. Объявите (в отельном заголовочном файле) и реализуйте (в другом файле) процедуры (они не возвращают значений!) согласно варианту. 2....

Передача массива по ссылке - C++
Здравствуйте, помогите разобраться с проблемой: Задание состоит в том, чтобы написать две встраиваемые функции сортировки массива с выбором...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
13.09.2012, 17:20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru