Как передать значения константного указателя в классах в C ++ - PullRequest
0 голосов
/ 17 апреля 2020

Я новичок в мире C ++ (и OOP). В данный момент я изучаю классы и указатели, но я застрял и надеюсь, что кто-то может объяснить мне, что я пропускаю, или должен глубже вникнуть, чтобы расширить мое понимание.

Пример 1 работает:

#include <iostream>
#include <string.h>
using namespace std;

class MyClass
{
private:
        char* age;

public:
        MyClass(const char* initData)
        {
                age = NULL;
                cout << "In default constructor working on pointers" << endl;
                age = new char [strlen(initData)+1];
                strcpy(age,initData);
                //age = initData;
        }

        ~MyClass()
        {
                cout << "In destructor working on pointers" << endl;
                delete [] age;
        }

        const char* GetAge()
        {
                return age;
        }
};

int main()
{
        //MyClass firstClass(10);
        //cout << "First attempt: " ;
        //cout << firstClass.GetAge() << endl;

        MyClass secondClass("A test from B");
        cout << "Second attempt: ";
        cout << secondClass.GetAge() << endl;

        return 0;
}

Однако это не работает:

#include <iostream>
#include <string.h>
using namespace std;

class MyClass
{
private:
        int* age;

public:
        MyClass(const int* initData)
        {
                cout << "In default constructor working on pointers" << endl;
                age = new int;
                //strcpy(age,initData);
                age = initData;
        }

        ~MyClass()
        {
                cout << "In destructor working on pointers" << endl;
                delete age;
        }

        const int* GetAge()
        {
                return age;
        }
};

int main()
{
        MyClass firstClass(10);
        cout << "First attempt: " ;
        cout << firstClass.GetAge() << endl;

        //MyClass secondClass("B");
        //cout << "Second attempt: ";
        //cout << secondClass.GetAge() << endl;

        return 0;
}

Я чувствую, что это связано с тем, что я передаю int в постоянный указатель. А затем попробуйте назначить константу из r-значения в l-значение с помощью оператора =. Хотя кажется, что это разрешено, так как я говорю «const int * initData», и это говорит компилятору не изменять данные, но адрес памяти может измениться?

Итак, в моем понимании, я передаю значение 10 в класс, который делает указатель в конструкторе по умолчанию, он создает адрес памяти и сохраняет его в initData. Затем я передаю r-значение InitData (адрес mem) в указатель возраста l-значения, который принимает адреса памяти.

Если я попробую с точно таким же кодом, но использую символ и скопирую данные в моем первом примере, это сработает ...

Может кто-нибудь объяснить мне, что мне не хватает, Спасибо в заранее!

Редактировать : Я думаю, что нашел свое решение и понял его лучше. Может ли кто-нибудь убедиться, что это правильно, или что (более) правильная форма:

Сценарий 1:

#include <iostream>
using namespace std;

class MyClass
{
private:
        int* age;

public:
        MyClass(const int *initData)
        {
                cout << "In default constructor working on pointers" << endl;
                age = new int;
                (*age) = (*initData);
        }

        ~MyClass()
        {
                cout << "In destructor working on pointers" << endl;
                delete age;
        }

        const int* GetAge()
        {
                 return age;
        }
};

int main()
{
        int aNum = 10;
        MyClass firstClass(&aNum);
        cout << "First attempt: " ;
        cout << *firstClass.GetAge() << endl;

        return 0;
}

Или Сценарий 2:

#include <iostream>
using namespace std;

class MyClass
{
private:
        int* age;

public:
        MyClass(const int &initData)
        {
                cout << "In default constructor working on pointers" << endl;
                age = new int;
                (*age) = (initData);
        }

        ~MyClass()
        {
                cout << "In destructor working on pointers" << endl;
                delete age;
        }

        const int* GetAge()
        {
                return age;
        }
};

int main()
{
        MyClass firstClass(10);
        cout << "First attempt: " ;
        cout << *firstClass.GetAge() << endl;

        return 0;
}

I Можно подумать решение 2, так как оно использует ссылку на память и, таким образом, ускоряет выполнение?

Спасибо за помощь, и извините за длинный пост ...

1 Ответ

0 голосов
/ 17 апреля 2020

Первое: вы не можете установить константный указатель на неконстантный указатель, вы можете обойти это, используя const_cast<int*>(initData), который избавляется от константности initData при присвоении age.

Но я не думаю, что это то, чего вы хотите достичь.

Итак, в первую очередь указатель просто указывает на память - поэтому память должна управляться кем-то другим, а не указателем. Обычно вам нужен только указатель, если вы хотите reference что-то или iterate - если вы намереваетесь стать владельцем этой памяти, вы можете не захотеть использовать указатель.

Во-вторых: если вы начинаете учиться C ++, попробуйте освоить «современный» C ++ и использовать smart_pointers (см. Форму «умных указателей» cppreference ).

Практическое правило: если вам не обязательно указатель (нет нужна итерация, прямой доступ к памяти) используйте by reference.

Но суть: ваш пример выглядит так, как будто он вообще не предназначен для использования с указателями. Просто сохраните значение int.

class MyClass
{
private:
        int age;

public:
        // pass by const reference, this is cheap and good practice
        MyClass(const int& initData)
        {
                cout << "In default constructor working on pointers" << endl;
                // here the value of initData is actually copied into age
                age = initData;
        }

И если вы действительно хотите попробовать указатели: начните с std::shared_ptr, который является простым в использовании указателем для подсчета ссылок.

Пример:

#include <memory>
#include <iostream>

class test
{
    private:
        std::shared_ptr<int> age;

    public:

        // cheap and quick const ref
        test(const std::shared_ptr<int>& data)
        {
            age = data;
        }

        void print()
        {
            std::cout << *age << std::endl;
            std::cout << "Use count: " <<  age.use_count() << std::endl;
        }

};

int main()
{
    // here we store the data
    int i = 17;
    // here we have the shared_ptr
    std::shared_ptr<int> p = std::make_shared<int>(i);
    // here we pass it to the object
    test t(p);
    t.print();

    return 0;
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...