throw calling move constructor even for lvalues

76 Views Asked by At

I have the following situation:

#include <iostream>

struct T {
    T() {
        std::cout << "default" << std::endl;
    }
    T (const T& t) {
        std::cout << "copy" << std::endl;
    }
    T (T&& t) {
        std::cout << "move" << std::endl;
    }
};
void g() {
    T t;
    throw t;
}
void h() {
    static T t;
    throw t;
}

int main(){
    try {
        g();
    } catch(T& t) {
        std::cout << "cautch" << std::endl;
    }
    std::cout << "---" << std::endl;
    try {
        h();
    } catch(T& t) {
        std::cout << "cautch" << std::endl;
    }
}

output on GCC 9.2 with c++11 flag:

default
move
cautch
---
default
copy
cautch

In cppreference is said that the object resulted from the expression in throw expression is copy-initialized. However, when the expression is rvalue, the move ctor is called. In h(), I have a lvalue in the throw expression, but the move ctor is called instead of the copy ctor. Why not copying in this case? I tested with static and then, copy ctor is called. Does it, in c++11, have something to do with lifetime?


Note that's not a question about copy elision. You can use -fno-elide-constructors. The result is the same.

If I have this f():

void f() {
    throw T();
}

I'm having copy elision, but I believe It's not the case I'm asking...


Answer:

"when the expression in a return statement is a id-expression that names an object with automatic storage duration declared in the body, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue"

0

There are 0 best solutions below