0

I've been working on a personal project where I code a simple Blackjack game, nothing too fancy. However, in an attempt to make copy assignment operators for my Card class, my CLion linter is suggesting that how I am writing them is incorrect and is suggesting an alternate method that I've never seen before.

Here is the header declaration for the Card class, with the main focus being on the copy assignment operator (exists within Card.h):

class Card
{
    private:
        int cardIndex; // each value from 0-52 represents a particular playing card,
                       // with 0 representing the back of a card
    public:
        Card();
        Card(int cardIndex);
        Card(const Card &otherCard);
        Card& operator=(const Card &otherCard);
        Card(Card &&otherCard) noexcept;             // undefined move constructor
        Card& operator=(Card &&otherCard) noexcept;  // undefined move assignment operator
        ~Card();
        int getIndex();
        void setIndex(int cardIndex);
        void display();
};

Here is how I tried to define it, with the CLion linter notably not color coding the class's data member that I know is declared (exists within Card.cpp):

&Card Card::operator=(const Card &otherCard)
{
    this->cardIndex = otherCard.cardIndex;
    return *this;
}

Here is what the CLion linter tried to autocomplete for me, which brings back the the color coding for the cardIndex data member as though it's able to recognize it exists only in this state:

&Card::operator=(const Card &otherCard)
{
    this->cardIndex = otherCard.cardIndex;
    return *this;
}

Correct me if I'm wrong but this should not be correct whatsoever, unless there's some syntactical reason that my code would be compiled correctly with this method signature I am yet unaware of. I highly doubt this is the case and that my linter is futzing something somewhere or I've made some grave mistake with my class declaration, but this wouldn't be the first time that CLion has revealed some weird thing to be more correct/be possible in the first place.

  • 3
    Typo: It should be `Card&`, not `&Card`. The linter is apparently not clever enough to recognize what you intended to write there. – user17732522 Jan 16 '22 at 17:51
  • 7
    Why are you writing your own assignment operators, copy constructor, etc. at all? All the default-generated ones will work perfectly well if `Card` just consists of a single `int` member variable. – Nathan Pierson Jan 16 '22 at 17:52
  • @NathanPierson honestly that's a very good point, I've just been used to manually writing them myself and forgot that I don't need to for primitive types. – KeyboardClone Jan 16 '22 at 17:58
  • @KeyboardClone It is rare that custom copy/move operations or destructors need to be defined. They are not needed for non-primitive types either. As long as you don't manage a ressource or use `new` (which you shouldn't), there is usually no need for them. That is known as the "rule of zero". – user17732522 Jan 16 '22 at 18:00
  • 3
    @NathanPierson points out the real typo. This is Rule of 0 code. – sweenish Jan 16 '22 at 18:00
  • @sweenish Yeah I already replied to what he said regarding that, I've been mostly messing with pointers that deal with dynamic memory when I was learning about move and copy semantics so it was just a knee jerk reaction to try and be safe when it's just unnecessary. Regardless, thanks for the help. – KeyboardClone Jan 16 '22 at 18:14
  • @user17732522 Yeah I've admittedly been forgetting some of these basic rules, I might need to refresh myself a little bit on some of these topics while I'm in college if I can find the time. I've been mostly dealing with ARM64 assembly during my past semester so some of the more basic stuff I knew about C++ kind've got forgotten in favor of the minutia required for that low level language. That said, I haven't heard of "don't use new", but I can wager a guess it probably has to do with using Smart pointers rather than raw ones (which my college education thus far has avoided for some reason). – KeyboardClone Jan 16 '22 at 18:19
  • @KeyboardClone Not just for primitive types but also anything that follows RAII and has a destructor to do the job and also supports copy and move operations. An example would be `std::vector` and other STL containers. – digito_evo Jan 16 '22 at 18:20
  • @digito_evo I wish I could say I knew that but I didn't, ty for the info I'll have to make a note of that somewhere. Honestly, I probably just should've known as it just seems to be a logical conclusion to come to. – KeyboardClone Jan 16 '22 at 18:23

0 Answers0