-1

I want a compiler (online/ offline) which will not do any copy elison. I want to see the actual output which we've learnt in theory of "constructor and destructors of c++".

Which constructor will be called for the statement "Student s3=func(s1, s4)". None of my copy constructor, parameterized constructor and overloaded assignment operator is called for this statement. Then, how is this object constructing?

I have tested using this compiler too: https://rextester.com/l/cpp_online_compiler_visual

#include<cstring>
#include<iostream>
using namespace std;
class Student
{
    char* name;
    int id;
public:
    Student(char* n, int i)
    {
        name= new char[strlen(n)+1];
        strcpy(name, n);
        id=i;
        cout<<"Constructor "<<name<<endl;
    }
    Student(const Student& s)
    {
        name= new char[strlen(s.name)+1];
        strcpy(name, s.name);
        id=s.id;
        cout<<"Copy constructor "<<name<<endl;
    }
    void operator = (const Student &s )
    {
        name= new char[strlen(s.name)+1];
        strcpy(name, s.name);
        id=s.id;
        cout<<"Assignment Operator "<<name<<endl;
    }
    ~Student()
    {
        cout<<"Destructing "<<name<<endl;
        delete[] name;
    }
};
Student func(Student s, Student t)
{
    return s;
}
int main()
{
    Student s1("abcd", 16);
    Student s4("wxyz", 17);
    Student s3=func(s1, s4);
}
Sanjida
  • 3
  • 1
  • Copy elision is **part of the language**. 'which we've learnt in theory of "constructor and destructors of c++"'. Your course sounds like it teaches an inaccurate, but probably still useful, model. – Caleth Apr 17 '19 at 10:04
  • @Caleth I am really sorry. I didn't want to mean that. I tried to mean, I want to see the output without copy elision. Thanks. – Sanjida Apr 17 '19 at 13:42

2 Answers2

3

I think you are mistaken. A copy constructor is clearly called.

To make this clearer, re-write your main function to:

int main()
{
    Student s1("abcd", 16);
    Student s4("wxyz", 17);
    cout << "initializing s3\n";
    Student s3=func(s1, s4);
    cout << "done\n";
}

And the output will be (the "comments" are not part of actual output, but comments by myself.)

Constructor abcd
Constructor wxyz
initializing s3
Copy constructor wxyz // for the second parameter of the function
Copy constructor abcd // for the first parameter of the function
Copy constructor abcd // for s3
Destructing abcd // for the first parameter of the function
Destructing wxyz // for the second parameter of the function
done
Destructing abcd
Destructing wxyz
Destructing abcd

To make this even clearer, you can re-write also your function to take reference parameters so that new instances are not created.

Student func(Student &s, Student &t)
{
    return s;
}
int main()
{
    Student s1("abcd", 16);
    Student s4("wxyz", 17);
    cout << "initializing s3\n";
    Student s3=func(s1, s4);
    cout << "done\n";
}

Then the output will be:

Constructor abcd
Constructor wxyz
initializing s3
Copy constructor abcd
done
Destructing abcd
Destructing wxyz
Destructing abcd

where you can see a copy constructor is called once, obviously to initialize s3.

Now, if you compile with with the gcc option -fno-elide-constructors (as Quentin suggested), the output will be: (comments not part of actual output)

Constructor abcd
Constructor wxyz
initializing s3
Copy constructor abcd // for the return value of the function
Copy constructor abcd // for s3
Destructing abcd // for the return value of the function
done
Destructing abcd
Destructing wxyz
Destructing abcd
Ignatius
  • 2,745
  • 2
  • 20
  • 32
  • Thank you so much. This is really kind. How to add the option "-fno-elide-constructors" in code blocks? – Sanjida Apr 17 '19 at 13:45
  • I don't know about Code Blocks, but try: https://stackoverflow.com/questions/33208733/how-to-add-compiler-flags-on-codeblocks – Ignatius Apr 17 '19 at 15:04
2

GCC (whether it is hosted online or not) has -fno-elide-constructors:

-fno-elide-constructors

The C++ standard allows an implementation to omit creating a temporary that is only used to initialize another object of the same type. Specifying this option disables that optimization, and forces G++ to call the copy constructor in all cases. This option also causes G++ to call trivial member functions which otherwise would be expanded inline.

In C++17, the compiler is required to omit these temporaries, but this option still affects trivial member functions.

Community
  • 1
  • 1
Quentin
  • 62,093
  • 7
  • 131
  • 191