Приклад того, коли вказівник const дуже застосовний, може бути продемонстрований таким чином. Подумайте, що у вас є клас з динамічним масивом всередині нього, і ви хочете передати користувачеві доступ до масиву, але не надаючи їм прав на зміну вказівника. Поміркуйте:
#include <new>
#include <string.h>
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const GetArray(){ return Array; }
};
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' '; //You can still modify the chars in the array, user has access
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
}
Що виробляє:
Вхідні дані
ставлять дані
Але якщо ми спробуємо це:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
Temp.GetArray() = NULL; //Bwuahahahaa attempt to set it to null
}
Ми отримуємо:
помилка: потрібне значення lvalue як лівий операнд присвоєння // Drat foiled again!
Так чітко ми можемо змінювати вміст масиву, але не вказівник масиву. Добре, якщо ви хочете переконатися, що покажчик має стійкий стан при передачі його назад користувачеві. Однак є один улов:
int main()
{
TestA Temp;
printf("%s\n",Temp.GetArray());
Temp.GetArray()[0] = ' ';
Temp.GetArray()[1] = ' ';
printf("%s\n",Temp.GetArray());
delete [] Temp.GetArray(); //Bwuahaha this actually works!
}
Ми все ще можемо видалити посилання пам'яті вказівника, навіть якщо ми не можемо змінити сам вказівник.
Отже, якщо ви хочете, щоб посилання на пам'ять завжди вказувало на щось (IE ніколи не змінюється, як це працює в даний час), то це дуже застосовно. Якщо ви хочете, щоб користувач мав повний доступ та модифікував його, тоді неконстація - це для вас.
Редагувати:
Зауваживши коментар okorz001 про неможливість призначити через те, що GetArray () є операндом правого значення, його коментар цілком правильний, але вищезазначене все-таки застосовується, якщо ви повинні повернути посилання на покажчик (я припускаю, що я припускав, що GetArray був посилаючись на посилання), наприклад:
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; } //Note & reference operator
char * &GetNonConstArray(){ return Array; } //Note non-const
};
int main()
{
TestA Temp;
Temp.GetArray() = NULL; //Returns error
Temp.GetNonConstArray() = NULL; //Returns no error
}
Повернеться в першій, що призведе до помилки:
помилка: призначення місцезнаходження лише для читання 'Temp.TestA :: GetArray ()'
Але друге відбудеться весело, незважаючи на потенційні наслідки внизу.
Очевидно, постане питання "чому ви хочете повернути посилання на покажчик"? Є рідкісні випадки, коли потрібно призначити пам'ять (або дані) безпосередньо оригінальному вказівнику, про який йдеться (наприклад, створення власного malloc / free або new / free front-end), але в цих випадках це посилання, що не стосується const . Посилання на const покажчик Я не натрапив на ситуацію, яка б його вимагала (хіба що, можливо, як оголошені змінні const-посилання, а не типи повернення?).
Подумайте, чи є у нас функція, яка бере покажчик const (проти тієї, яка не відповідає):
class TestA
{
private:
char *Array;
public:
TestA(){Array = NULL; Array = new (std::nothrow) char[20]; if(Array != NULL){ strcpy(Array,"Input data"); } }
~TestA(){if(Array != NULL){ delete [] Array;} }
char * const &GetArray(){ return Array; }
void ModifyArrayConst(char * const Data)
{
Data[1]; //This is okay, this refers to Data[1]
Data--; //Produces an error. Don't want to Decrement that.
printf("Const: %c\n",Data[1]);
}
void ModifyArrayNonConst(char * Data)
{
Data--; //Argh noo what are you doing?!
Data[1]; //This is actually the same as 'Data[0]' because it's relative to Data's position
printf("NonConst: %c\n",Data[1]);
}
};
int main()
{
TestA Temp;
Temp.ModifyArrayNonConst("ABCD");
Temp.ModifyArrayConst("ABCD");
}
Помилка в const видає таким чином повідомлення:
помилка: зменшення параметра "Дані" лише для читання
Що добре, оскільки ми, мабуть, не хочемо цього робити, якщо тільки ми не хочемо викликати проблеми, зазначені в коментарях. Якщо ми редагуємо декремент у функції const, відбувається таке:
NonConst: A
Const: B
Зрозуміло, що навіть якщо A є "Дані [1]", це трактується як "Дані [0]", тому що покажчик NonConst дозволив операцію декременту. Як реалізується const, як пише інша людина, ми виявляємо потенційну помилку ще до її появи.
Ще одним головним моментом є те, що вказівник const може бути використаний як псевдопосилання, оскільки те, що опорні точки не можуть бути змінені (можна задатись питанням, чи можливо це було, як воно було реалізовано). Поміркуйте:
int main()
{
int A = 10;
int * const B = &A;
*B = 20; //This is permitted
printf("%d\n",A);
B = NULL; //This produces an error
}
При спробі компіляції видається така помилка:
помилка: присвоєння змінної лише для читання "B"
Що, мабуть, погано, якщо потрібно було постійне посилання на А. Якщо B = NULL
це буде прокоментовано, компілятор із задоволенням дозволить нам змінити, *B
і тому А. Це може здатися не корисним для ints, але врахуйте, якщо ви мали єдину позицію графічного додатку, де ви хотіли б не зміненого вказівника, який посилався на нього, що ви можете передати навколо.
Це використання є змінним (вибачте від ненавмисного каламбура), але правильно використовується, це ще один інструмент у вікні для допомоги у програмуванні.