nakhodkin
nakhodkin

Reputation: 1465

Why copy constructor is getting called?

I have the following piece of code and there are a couple of things that bother me the most:

  1. At what point in time does original constructor call happen?
  2. Under which circumstances, the copy constructor is getting called?
#include <iostream>
#include <functional>

class Samp {
    char str[10] = "Default";
public:
    Samp(char s[]) { strcpy(str, s); printf("Constructor\n"); }
    Samp(const Samp& s) { printf("Copy Constructor\n"); }
    ~Samp() { printf("Destructor\n"); }

    char* out() {
        return str;
    }

    friend std::ostream& operator<<(std::ostream& stream, const Samp& s) {
        stream << s.str;

        return stream;
    }
};

void output(Samp s) {
    std::cout << s << std::endl;
}

int main(int argc, const char * argv[]) {
    std::function<void(Samp s)> o;
    o = output;

    o((char*)"Hello");

    return 0;
}

On execution, the program provides the following output

Constructor
Copy Constructor
Default
Destructor
Destructor
Program ended with exit code: 0

enter image description here

Upvotes: 3

Views: 227

Answers (3)

M.M
M.M

Reputation: 141544

The arguments to a std::function invocation are passed by perfect forwarding through to the callable object stored inside the std::function object.

So the behaviour of o(args...) is not the same as output(args...). Instead it is the same as:

output( std::forward<Args...>(args...) );

or in this concrete example,

output( std::forward<Samp>( (char *)"Hello" ) );

In this example we see that "perfect" forwarding is not so perfect, as this code has slightly different behaviour to output( (char *)"Hello" ); .

The signature of the chosen overload for forward is Samp&& forward(Samp&& arg);. So there must be a temporary materialized for the arg to bind to for the function call tostd::forward; that is the "Constructor" that you see.

Then the "Copy constructor" is initialization of the output function's parameter from the return value of std::forward. That could be a move operation, if Samp had a move-constructor.

Upvotes: 5

void output(Samp s)

This is the problem. This function pass object by value. When you call

o((char*)"Hello")

, it creates an temporary Samp object by default constructor, and create another new object by copy constructor to pass to the function.

Upvotes: 2

Dies_Irae
Dies_Irae

Reputation: 37

Constructor and Copy of you class called in one place basicly. When you use youre function its create Samp S by construct and then copy it to void fnc.

Upvotes: 2

Related Questions