0

I have the following issue with reference parameters: When we have a function with reference parameters, the compiler will automatically pass to that function, the address of any argument it is called with. Example (with object):

class sample {
char *s;
public:
    sample(); // normal constructor
    sample(const sample &ob); // copy constructor
    ~sample( ) { if(s) delete [] s; cout << "Freeing s\n"; }
    void show() { cout << s << "\n"; }
    void set(char *str);
};// Definition will be excluded from here`

and we have a function with reference parameters of this class instance,

like:

void funtionWithRef(sample &kk); // declaration
void funtionWithRef(sample &sam){ // definition
    sam.show();
}

and one function with return object of type sample:

sample functionReturnSample(); //declaration
sample functionReturnSample(){ // definition
    sample sam;
    sam.set("test sample");
    return sam;
}

Now, when we do:

int main() {
    sample temp = functionReturnSample();
    funtionWithRef(temp);

    return 0;
}

It works perfect. When we put temp object as an argument to funtionWithRef, compiler pass address of that object to the function. But WHY it does not work, if we do NOT first assign a returning value of functionReturnSample to the instance, but directly put that method as an argument like :

funtionWithRef(functionReturnSample());

Why is this different, when we are doing the same thing, and according to some books I consulted, whit SHOULD

EDIT

@user657267 This is the full example (source book: C++ From Ground Up, 3rd Edition, page 219-320):

class sample {
    char *s;
    public:
        sample(); // normal constructor
        sample(const sample &ob); // copy constructor
        ~sample( ) { cout << "s: " << s <<" ,Freeing s\n"; if(s) delete [] s;}
        void show() { cout << s << "\n"; }
        void set(char *str);
        sample operator=(sample &ob); // overload assignment
};
// Normal constructor.
sample::sample() {
    s = new char('\0'); // s points to a null string.
    cout << "Normal constructor: s: " << strlen(s) << endl;
}
// Copy constructor.
sample::sample(const sample &ob) {
    cout << "Copy constructor: ob.s: "<< ob.s << " ,strlen(ob.s): " <<  strlen(ob.s) << "\n";
    s = new char[strlen(ob.s)+1];
    strcpy(s, ob.s);
}
// Load a string.
void sample::set(char *str) {
    s = new char[strlen(str)+1];
    strcpy(s, str);
}
// Overload assignment operator.
sample sample::operator=(sample &ob) {
    /* If the target memory is not large enough
    then allocate new memory. */
    cout << "operator= strlen(ob.s): " << strlen(ob.s) << " ,strlen(s): " << strlen(s) << endl;

    if(strlen(ob.s) > strlen(s)) {
        cout << "operator= Larger memory of target object. Deleting current...\n";
        delete [] s;
        s = new char[strlen(ob.s)+1];
    }
    strcpy(s, ob.s);

    return *this;
}
// Return an object of type sample.
sample input() {
    char instr[80];
    static sample str;
    cout << "Enter a string: ";
    cin >> instr;
    str.set(instr);

    return str;
}

int main() {
    sample ob;
    // assign returned object to ob
    ob=input(); // This is now OK
    ob.show();

    return 0;
}

This wont compile, and reports error:

**error: no match for ‘operator=’ (operand types are ‘sample’ and ‘sample’)**

So it is copy/past of the code from the mentioned book. You can check please.

However I figureout if I specify overloaded = operator arguments to be const like:

 sample operator=(const sample &ob); // overload assignment

Then it DOES work. However, what is bothering me is, now when I have runnable code, I do not get why TWO times copy constructor is called. I know it is called when input() function returns, and create temporary object, but I do not get why second time since, as much as I know (but maybe I am wrong) copy constructors are NOT called for assignment operations (same Book, pages 291-292), but it looks like, despite of that, when return *this; is called (when overloaded operator returns value), copy constructor is called? So what is about that ? Thankx

Creator
  • 21
  • 1
  • 6
  • 3
    Because a non-`const` lvalue reference cannot bind to a temporary, I seriously doubt any book would tell you otherwise. – user657267 Jun 11 '15 at 08:45
  • This is my understanding, whenever the statement `sample temp = functionReturnSample();` is executed, the copy constructor is evoked (since you have not overloaded `=` operator). Thus the `temp` object exist in the scope of main. Considering the next situation when `funtionWithRef(functionReturnSample())` is called it is different because the object `sam` created in the function is already destroyed if you come outside the function. There exist no valid object. hope it is clear – Bharadwaj Jun 11 '15 at 08:49
  • @user657267 , please, have a look at my EDITED post. Thanx – Creator Jun 11 '15 at 10:12
  • @Creator I managed to find the book, you are not at fault the book has an error. The assignment operator should be defined as `sample operator=(sample const &ob);`. Anyway, you might want to consider using a more recent reference, as modern C++ has changed somewhat and you might end up learning bad habits. – user657267 Jun 11 '15 at 11:56

0 Answers0