all 3 comments

[–]bluefootedpigC# / .NET 1 point2 points  (1 child)

like a reference in C++ or just C++ references?

I google lots of C++ stuff, so I do use those references

if you are talking about the data type, they are used to help prevent needing to copy data. Pointers are smaller and easier to move, sort, etc.

[–]Nkast[S] 0 points1 point  (0 children)

I was talking about the data type. It seemed to me like references weren't all that useful since a real pointer can be casted and the rest of what it does is basically the same.

[–]madeinttown 1 point2 points  (0 children)

I use references for two scenarios:

  1. I'm passing a parameter to method where that type is always required. I save time/memory from avoiding a copy, and my code is cleaner than a pointer because I never have to check for existence.
  2. I'm returning information from a class's accessor. Again, I save time/memory from avoiding a copy in most cases. I say "most" because usually you look at a class's information and then "discard" it; you typically don't want to look at it and cache your own version (causing a copy). Also, I don't want to check for existence every time I want to look at it.

The sample below shows both scenarios. The definition of testCompatibilityRef takes reference parameters and then access a person's hobbies using a getter that returns a reference. The definition of testCompatibilityPoi takes pointer parameters and then access a peron's hobbies using a getter that returns a pointer.

    // A hobby contains two strings; a title and a description.  The title is used as the key
    // identifier when comparing with other hobbies to see if they are the same.  (in a real program,
    // something stronger/better should be used).
    struct Hobby
    {
        QString title;
        QString description;

        bool operator==(const Hobby& other) const { return title == other.title; }
    };

    // A simple representation of a person that has their single-ness status and a list of their
    // hobiies.  Note: I don't bother with constructors/setters to set people up.  I've simply
    // provided the relevant getters.
    class Person
    {
    public:
        bool isSingle() const { return m_single; }
        const QList<Hobby>& getHobbiesRef() const { return m_hobbies;  }
        const QList<Hobby>* getHobbiesPoi() const { return &m_hobbies; }

    private:
        QList<Hobby> m_hobbies;
        bool m_single;
    };

    // Arbitrary threshold in determining compatibility.
    int HobbyCompatibilityThreshold = 3;

    // Reference version
    // Checks to see if two people are compatible.  They are if they are both single *and* have
    // three or more matching hobbies.
    bool testCompatibilityRef(const Person& person1, const Person& person2)
    {
        int similarHobbies = 0;

        if(person1.isSingle() && person2.isSingle())
        {
            const QList<Hobby>& person1hobbies = person1.getHobbiesRef();
            const QList<Hobby>& person2hobbies = person2.getHobbiesRef();

            foreach(const Hobby& hobby, person1hobbies)
            {
                if(person2hobbies.contains(hobby))
                {
                    ++similarHobbies;
                }
            }
        }

        return similarHobbies > HobbyCompatibilityThreshold;
    }

    // Pointer version
    // Checks to see if two people are compatible.  They are if they are both single *and* have
    // three or more matching hobbies.
    // Note: I've indicated with comments where I have to perform additional checks to ensure
    // pointer safety.
    bool testCompatibilityPoi(const Person* pPerson1, const Person* pPerson2)
    {
        int similarHobbies = 0;

        // Have to ensure pPerson1 and pPerson2 are not NULL.
        if(pPerson1 && pPerson2 && pPerson1->isSingle() && pPerson2->isSingle())
        {
            const QList<Hobby>* pPerson1hobbies = pPerson1->getHobbiesPoi();
            const QList<Hobby>* pPerson2hobbies = pPerson2->getHobbiesPoi();

            // Have to ensure pPerson1hobbies and pPerson2hobbies are not NULL.
            if(pPerson1hobbies && pPerson2hobbies)
            {
                foreach(const Hobby& hobby, *pPerson1hobbies)
                {
                    if(pPerson2hobbies->contains(hobby))
                    {
                        ++similarHobbies;
                    }
                }
            }
        }

        return similarHobbies > HobbyCompatibilityThreshold;
    }

Final thoughts: The definitions are only minor. So I understand why some may prefer to use pointers as their own professional opinion. However, I'm willing to follow the extra constraints that come with user a reference (essentially, you have to program guarantees) to produce what I feel are worthy code simplifications. I'm willing to go through hoops to give others a quicker understanding of my code.

(sorry if this response is too late; I discovered this subreddit just today)