Home > Mobile >  how to initialize a class object reference in C to simulate NRVO?
how to initialize a class object reference in C to simulate NRVO?

Time:05-15

I meet a course programming problem, which asks me to initialize the A a using passing by reference (initialize the A a in the func). How can I call A's constructor by A's reference?

#include <iostream>
using namespace std;

class A
{
public:
    int x;
    A()
    {
        cout << "default constructor" << endl;
        x = 1;
    }

    A(int x)
    {   
        cout << "constructor with param = "  << x << endl;
        this->x = x;
    }

    ~A() {
        cout << "destructor" << endl;
    }

    void print() {
        cout << x << endl;
    }
};


void fun(A& a)
{
    a.A::A(10); // error!
    return;
}


int main()
{
    A a; 
    fun(a);
    a.print();
    return EXIT_SUCCESS;
}

There is a background of this problem. The teacher want us to replicate the NRVO(named return value optimization) result.

#include <iostream>
using namespace std;

class A
{
public:
    int x;
    A()
    {
        cout << "default constructor" << endl;
        x = 1;
    }

    A(int x)
    {   
        cout << "constructor with param = "  << x << endl;
        this->x = x;
    }

    ~A() {
        cout << "destructor" << endl;
    }

    void print() {
        cout << x << endl;
    }
};

A fun() {
    A a = A(10);
    return a;
}


int main()
{
    A a = fun();
    return EXIT_SUCCESS;
}

default g compiler:

constructor with param = 10
destructor

if we close the NRVO: g test.cpp -fno-elide-constructors

constructor with param = 10
destructor
destructor
destructor
destructor

The teacher want us to replicate the NRVO(named return value optimization) result by passing by reference.

CodePudding user response:

The syntax a.A::A(10); is incorrect.

Constructor is used to create an object of a class, you cannot call it on an already existing object. Even a constructor cannot be explicitly called. It is implicitly called by the compiler.

From general-1.sentence-2:

Constructors do not have names.

Thus, you cannot call a constructor explicitly. The compiler will automatically call the constructor when an object of that class-type is created.

CodePudding user response:

You can not, not like this.

A reference always points to an initialized object. So you already failed before you called the function. The "return" argument is already initialized. And you can't initialized an initialized value again, not legally.

You can cheat by calling

std::construct_at(&a, 10);

For it to really reflect NRVO you could have something like this:

void fun(A *a)
{
    std::construct_at(a, 10);
}

union UninitializedA {
    std::byte uninitialized[sizeof(A)];
    A a;
};

int main()
{
    UninitializedA u;
    fun(&u.a);
    u.a.print();
    u.a.~A();
    return EXIT_SUCCESS;
}
  • Related