Адреса переменных в конструкторе, когда объект вставляется в std :: map - PullRequest
0 голосов
/ 29 сентября 2019

Я действительно не понимаю результат этого кода:

struct exampleClass
{
    double a = 12.1;
    std::map<int, double*> innerMap;

    exampleClass()
    {
        std::cout << "ADR of  variable a in constructor = " << &a << std::endl;
        std::cout << "ADR of this in constructor = " << this << std::endl;
        innerMap.emplace(4,&a);
    }
};


int main(){
    std::map<int, exampleClass> map;
    map.insert(std::make_pair(4, exampleClass{}));


    for (auto& it : map)
    {
        std::cout << "ADR of a = " << &(it.second.a) << std::endl;
        std::cout << "Content of a = " << it.second.a << std::endl;
        std::cout << it.second.innerMap.find(4)->second << std::endl;
        std::cout << *(it.second.innerMap.find(4)->second); //the output is wrong
    }
}

Результат:

ADR of  variable a in constructor = 0x7ffee080b500 

ADR of this in constructor = 0x7ffee080b500

ADR of a = 0x559ddb2c42e8

Content of a = 12.1

0x7ffee080b500

6.95312e-310

Я не понимаю, почему адреса в цикле forотличаются от адресов в конструкторе.Также «адрес конструктора» используется для вставки в innerMap, что вызывает ошибку.

Может ли кто-нибудь объяснить мне это?

Что меня смущает, так это следующееожидается:

exampleClass abc{};
std::cout << "ADR of a = " << &(abc.a)<< std::endl;
std::cout << *(abc.innerMap.find(4)->second) << std::endl;

Ответы [ 2 ]

2 голосов
/ 29 сентября 2019

Здесь:

map.insert(std::make_pair(4, exampleClass{}));

был создан временный экземпляр exampleClass, с exampleClass::innerMap, правильно указывающим на exampleClass::a этого экземпляра.Но сразу после этого он перемещается - через пару в map.Содержимое exampleClass::innerMap остается тем же, то есть указатель, сопоставленный с 4, остается тем же, но после того, как временный экземпляр исчез, он становится недействительным.

Решение: исправьте семантику конструктора копирования / перемещениявашего класса, придерживаясь правил трех / пяти .Единственное, что вы можете выяснить, это использовать new / delete для этих указателей везде.Но мы этого не делаем.Если a предназначен для использования по умолчанию для всех экземпляров класса, он должен быть static.Таким образом, это переживет все случаи, и эта проблема не будет существовать.В противном случае используйте умные указатели.

0 голосов
/ 29 сентября 2019

Согласно первому ответу, самописанный конструктор перемещения отсутствует, так как std :: make_pair () вызывает конструктор перемещения по умолчанию, который не заботится о специальной ситуации.Следующий конструктор перемещения решит проблему:

exampleClass(exampleClass&& other)
{
    this->innerMap.insert(std::make_pair(4, &(this->a)));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...