Почему объектным функциям C ++ нужны переменные-члены ссылочного типа?

Это вопрос новичка в C ++. Я читал статью «Функциональный объект» в Википедии. В статье есть пример на C ++, подобный следующему:

struct printClass {
int &count;

printClass(int &n) : count(n) {}

void operator()(int &i) const {
count++;
cout << i << "[" << count << "] ";
}
};

int main(int argc, char** argv) {
vector<int> a(5, 7);
a[4] = -1;
a.resize(10, 3);
int state = 0;
for_each(a.rbegin(), a.rend(), printClass(state));
}

У меня есть 2 вопроса:

  1. Почему он не компилируется, когда count является обычной переменной, а не ссылочным типом? демонстрация

  2. Почему он не компилируется, я изменяю ctor к следующему? демонстрация

    printClass(int &n) { count = n; }

Благодарю.

РЕДАКТИРОВАТЬ: Спасибо за объяснение. Я вижу, что следующая версия тоже работает. Есть ли причина для выбора одного над другим?

struct printClass {
int count;

printClass(int n) { count  = n; }

void operator()(int &i) {
count++;
cout << i << "[" << count << "] ";
}
};

РЕДАКТИРОВАТЬ: На основании ответа iammilind, вот третья версия, которая работает тоже с использованием const_cast<int &>,

struct printClass {
int count ;

printClass(int n) : count(n) {}

void operator()(int &i) const {
const_cast<int &>(count)++;
cout << i << "[" << count << "] ";
}
};

4

Решение

(1) Почему он не компилируется, когда count является обычной переменной, а не
ссылочный тип?

Это очень интересный вопрос. Вопрос должен быть скорее, почему код компилируется, когда count объявлен в качестве ссылки. 🙂

Обычная переменная не работает, потому что int count не может быть изменено внутри const квалифицированная функция operator()(int &i) const;,

Рекомендации немного отличаются. В вашем коде вы объявляете метод как const, Который означает, что count что относится к iТеперь не может ссылаться на что-либо еще.
Но это все равно невозможно из-за характера ссылок :). Нельзя изменить привязку ссылки после инициализации.
operator() просто проверяет, меняете ли вы привязку count к чему-то еще или нет? И ответ всегда — нет. Так как count++ изменяет значение, указанное count а не обязательный.

В вашем коде не имеет значения, является ли метод-член const или нет, когда дело доходит до int& count,

Относиться int& count; в int* const p_count; и попробуйте смоделировать ситуацию самостоятельно.

(2) Почему он не компилируется, я меняю ctor на следующий?
CountFrom(int &n) { count = n; }

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

int i, &r;  // error, because 'r' not initialized
r = i;  // this is not initialization but a copy

Кстати, вы должны быть особенно осторожны, когда имеете дело со ссылочными переменными внутри class, Потому что это легко испортить их масштабы и обоснованность.
Например, здесь действительность count зависит от объема i,

редактировать: После вашего второго редактирования очень просто знать, почему эта версия работает.
Так как count теперь простая переменная. Его можно пропустить из инициализации в списке инициализатора конструктора в отличие от ссылки.
Кроме того const правильность operator() ушел, поэтому любая переменная-член class теперь можно изменить внутри него.

Вы должны выбрать const версия метода-члена, если вы хотите заявить, что нет class член «должен» измениться внутри него (если не mutable или вы используете const_cast). Во всех остальных случаях используйте обычную версию метода member. Они оба могут сосуществовать в зависимости от вашей бизнес-логики. Это довольно широкий вопрос, и для этого стоит иметь другую ветку.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]