Неинициализированное значение при работе с shared_ptr - PullRequest
0 голосов
/ 15 мая 2019

Я уверен, что это очень просто, но я довольно новичок в интеллектуальных указателях, и я не смог найти ответ на этот вопрос.

Сценарий очень прост: у меня есть класс А,который содержит shared_ptr для некоторого объекта X:

class A{
    shared_ptr<const X> _asX;
}

, теперь после серии вызовов функций я создаю новый объект типа B, который также содержит этот X. что-то вроде:

class B {
private:
    shared_ptr<const X> _bsX;
public:
    B(): _bsX(nullptr) // - maybe this is problematic {}
    foo(shared_ptr<const X>& x)
    {
        _bsX = x;
        // The line above gives me undefined behavior, 
        // and when I run valgrind I get "Conditional jump or move
        // depends on uninitialized value(s)",
        // telling me this is not the correct way to do things. 
    }

Обратите внимание, что намеренно foo действительно устанавливает значение _bsX, а не конструктор.

Так, как указано выше - в зависимости от компилятора, я получаю ошибки сегментации - что обычно означает, что какое-то значение не было инициализировано, а позже подтверждено valgrind.

Итак, что мне делать - я пытался использовать «сброс» и т. Д., Но я так растерялся, что прошу вашей помощи.Может ли это быть const?или передать по ссылке?или оператор '='.

И в то время как мы находимся на этом - я должен передать X с его оберткой (shared_ptr) в foo, или я должен передать необработанный указатель, а затем сделать его общим?если так - не могли бы вы привести пример.Я тоже это попробовал и получил ошибки.

1 Ответ

1 голос
/ 15 мая 2019

Хорошо, я нашел проблему, и она вообще не имеет отношения к умным указателям, но так как я новичок в этом - я подумал, что это может быть.Я оставлю этот ответ для будущих ссылок.Вот что я сделал (упрощенно):

class A{

private:

    shared_ptr<const int> _num;

public:
    A()
    {
        _num = make_shared<const int>(5);
    }

    const shared_ptr<const int>& getNum() const {return _num; }

    void printNum()
    {
        cout << *_num.get() << endl;
    }
};

class B
{


public:

    struct C{
        C() : _num(nullptr){}
        void boo(shared_ptr<const int> & num) { _num = num;}
        shared_ptr<const int> _num;
    };

    B() {}

    void foo(shared_ptr<const int>& num)
    {
        cs.reserve(2);
        for (uint32_t i = 0; i < 2 ; ++i) {

            cs.push_back(C()); // This was missing.
            cs[i].boo(num);
        }
    }

    void printCNum()
    {
        for (C c : cs) {
            cout << *c._num.get() << endl;
        }
    }

private:

    vector<C> cs;
};


int main()
{
    A a{};
    shared_ptr<const int> xx = a.getNum();

    B b{};
    b.foo(xx);

    a.printNum();
    b.printCNum();

}

Глупый я, я думал, что когда вы резервируете вектор объектов (не указателей / ссылок), он также вызывает их конструктор.Оказывается, это не так.Конкретно я увеличил емкость вектора, а не его размер.

...