Попытка инициализировать элемент данных в конструкторе, но это не удается. Зачем?

Переменные-члены указателя структуры возвращают неправильное число.

Вот объявление структуры:

struct Obj {
int val;
Obj(int val) { val = val; }
};

Вот где это становится забавным:

Obj* cool = new Obj(4);
cout << cool->val; // outputs a number that's not 4
cout << (cool->val == 4); // prints 0... interesting

0

Решение

Почему я получаю эти странные цифры?

Вы никогда не инициализируете Obj::valтаким образом, значение — это то, что происходит в этой ячейке памяти в момент создания экземпляра Obj,


ПРИЧИНА: Имена играют «скрывать & искать»

struct Obj {
int val;         // (A)
Obj(int val) {   // (C)
val = val;     // (B)
}
};

Внутри конструктора Obj названный параметр val прячет Данные членов названный val; другими словами, вы присваиваете значение аргумента с именем valк аргументу по имени val,

Стандарт гласит, что переменная, объявленная в более узкой области видимости, чем предыдущая, будет эффективно скрывать старую.

Это означает, что, поскольку аргумент val в (В) находится в более узком объеме, чем (), в точке (С) компилятор думает, что вы ссылаетесь на аргумент.


Предлагаемые решения

У вас есть несколько вариантов решения этой проблемы

this->val = val;              // (A)
Obj::val  = val;              // equivalent

Obj (int val) : val (val) { } // (B)

Obj (int foo) { val = foo; }  // (C)

  • ), используйте this->val явно указать, что вы хотите присвоить значение члену данных Obj

  • В), использовать мем-инициализатор где Obj::val не будет скрыто именем аргумента

  • С), измените имя вашего аргумента


мем-инициализатор выглядит жутким, почему это включено?

Вне Предлагаемые решения, решение помечено (В) является предпочтительным.

Это называется с помощью мем-инициализатор, и инициализирует член вал со значением аргумента вал непосредственно по вызову конструктора; вместо этого сначала необходимо инициализировать по умолчанию, а затем присвоить значение.

Рекомендуется также не иметь аргументов с тем же именем, что и переменные-члены, так как это может быть подвержено ошибкам, если забыть о Имя скрытие.

Общий дизайн — это префикс каждого Данные членов с m_ явно указать, что таковой действительно является элемент экземпляра, например, в следующем фрагменте:

struct Obj {
Obj(int val) : m_val (val) { }
int m_val;
};
7

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

Это:

Obj(int val) { val = val; }

просто присваивает параметр себе и оставляет переменную-член, содержащую мусор. Тебе нужно:

Obj(int val) : val(val) {}

или (если вам действительно нужно назначить, а не инициализировать):

Obj(int val) { this->val = val; }

или же:

Obj(int the_val) { val = the_val; }

Вы можете рассмотреть возможность использования соглашения об именах для членов:

int m_val;
Obj(int val) : m_val(val) {}
2

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