1

Is it able to return an object without calling the copy constructor in C++?

In my sample codes, returning an object does not call the copy constructor even though the returned object has same member variable values, and the returning object and l-value of it even have same memory address.

How can is this possible?

Here is the my codes.

#include <iostream>

class foo {
public:
    foo(int v) : value{v}
    {
        std::cout << "default constructor" << std::endl;
    }

    foo(const foo &v)
    {
        std::cout << "copy constructor" << std::endl;
        this->value = v.value;
    }

    foo(foo &&v) = delete; 

    foo &operator=(const foo &v)
    {
        std::cout << "copy assignment" << std::endl;
        if (this == &v) {
            return *this;
        }
        this->value = v.value;
        return *this;
    }

    foo &operator=(foo &&v) = delete; 

    void print()
    {
        std::cout << this->value << std::endl;
    }

private:
    int value = 0;
};

foo func()
{
    foo v{10};
    std::cout << "returning " << &v << std::endl;
    return v;
}

int main()
{
    foo v = func();
    std::cout << "v is " << &v << std::endl;
    v.print();
    return 0;
}

And here is the output of the codes.

default constructor
returning 0x7ffeef00e034
v is 0x7ffeef00e034
10

I compiled the codes as follows:

g++ -std=c++17 -Wall -Wextra -g main.cpp
Brian
  • 1,663
  • 5
  • 18
  • 26
  • 2
    Search the web for "copy elision". – n. m. could be an AI Apr 05 '22 at 07:37
  • 2
    [copy elision](https://en.cppreference.com/w/cpp/language/copy_elision)? – Raildex Apr 05 '22 at 07:37
  • 1
    If you wonder how it's implemented, typically, a caller allocates storage and passes its address to a callee (as a "hidden" argument; usually through a register according to the applied calling conventions/ABI). That is why the callee can initialize the object directly in this storage. No copy/move is then needed. – Daniel Langr Apr 05 '22 at 08:18
  • 1
    Erm. I believe that’s NRVO (or whatever it’s called, these days). You could check by trying `return (v);` (with parens… Though, that may have been addressed in defect report at some point). Sorry, I don’t have links on mobile check cppreference for nrvo – viraltaco_ Apr 05 '22 at 11:31

0 Answers0