0

I implemented a class following the rule of three, and I am getting a crash. Upon debugging I have came to the conclusion that the copy constructor is calling itself repeatedly instead of calling the equality operator. Why is this so? Shouldn't it call the equality operator?

#include <iostream>
#include <deque>
#include <cstdlib>
#define LENGTH 128

typedef struct tDataStruct
{

char strA[LENGTH];

char strB[LENGTH];
int nNumberOfSignals;
double* oQueue;

tDataStruct()
{
    nNumberOfSignals = 0;
    //oQueue = NULL;
    memset(strA, 0, LENGTH);
    memset(strB, 0, LENGTH);
}

~tDataStruct()
{
    if (NULL != oQueue)
    {
        delete[] oQueue;
        oQueue = NULL;
    }
}

tDataStruct(const tDataStruct& other) // copy constructor
{
    if (this != &other)
    {
        *this = other;
    }

}
tDataStruct& operator=(tDataStruct other) // copy assignment
{
    if (this == &other)
    {
        return *this;
    }
    strncpy_s(strA, other.strA, LENGTH);
    strncpy_s(strB, other.strB, LENGTH);
    nNumberOfSignals = other.nNumberOfSignals;
    if (NULL != oQueue)
    {
        delete[] oQueue;
        oQueue = NULL;
    }
    if (other.nNumberOfSignals > 0)
    {
        //memcpy(oQueue, other.oQueue, nNumberOfSignals);
    }
    return *this;
}
} tDataStruct;


int main()
{
    tDataStruct tData;

    std::deque<tDataStruct> fifo;

    fifo.push_back(tData);
}
3
  • If you used std::array<char, LENGTH> instead of char [LENGTH] and std::vector<double> instead of double* all the compiler generated members would behavior correctly. Commented Oct 10, 2018 at 13:46
  • This is not the standard way of doing it. Normally the assignment operator uses the copy constructor in an idiom called "Copy and Swap" (look it up). As a result of doing it this way you have a serious bug that is causing UB (delete[] oQueue is potentially called on an un-initialized variable. Thus you are randomly deleting some part of memory (not a good idea). Commented Oct 10, 2018 at 14:11
  • Yes I have found out about that bug. Thanks Commented Oct 10, 2018 at 14:12

2 Answers 2

7

In your copy constructor you use

*this = other; //(1)

which calls

tDataStruct& operator=(tDataStruct other)  //(2)

as other is passed by value it needs to make a copy. That then calls 1, which call 2 which then calls 1 which then calls 2 and a round and a round you'll go until the program crashes/terminates.

You need to take other by reference so you don't actually make a copy like

tDataStruct& operator=(const tDataStruct& other) 

All that said you are doing this backwards. You should use the copy and swap idiom and implement your operator = by using your copy constructor.

Sign up to request clarification or add additional context in comments.

Comments

0

Your copy constructor calls assignment:

tDataStruct(const tDataStruct& other) // copy constructor
{
    // NOTE: this redundant check is always true. 
    // Please remove the if.
    if (this != &other) 
    {
        *this = other;
    }
 }

Then, since assignment operator gets the object by value (and not by reference), a copy constructor is called in order to copy the parameter:

tDataStruct& operator=(tDataStruct other) // copy assignment
{

This is how you got mutual recursion.

Try passing by reference instead:

tDataStruct& operator=(const tDataStruct &other) // copy assignment

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.