简体   繁体   中英

C++14 Function returns array of objects although copy constructor is deleted

from the old C++98 i am aware, that return types a copied (by value) if not mentioned in the function declaration/definition otherwise with the address operator '&'.

Now i am playing around with the concepts of auto and decltype to let the compiler determin the return type. In an example i worte a class A where with exception of the default ctor any other ctors are deleted (class A is taken from a real project - and i investigate some issues). An object of the class A is contructed together with an etl::array (Embedded template library, Array created on the stack with fixed size ), see example code below.

#include <etl/array.h>
#include <iostream>

class A {
public:
    A(std::uint8_t val) : _val(val){}
    A(A const&) = delete;      // copy delete
    A& operator=(A&) = delete; // copy assign delete
    A(A&&) = default;          // move default
    A& operator=(A&&) = delete;// move assign delete
    ~A() = default;
    void whoAmI(){std::cout << " I am A! " << std::endl;}
private:
    std::uint8_t _val;
};

decltype(auto) X(std::uint8_t val) {
  return etl::array<A,1>{A{val}};
}

int main()
{
    decltype(auto) x = X(5U);
    for (auto& it : x) {
      it.whoAmI();
    }
}

I would expect, that the etl::array will be copied in the main() routine and assigned to the local variable x. I would not expect to have a copy of A in the array, due to the deleted copy ctor. However, the code compiles and i am able to call the function on the element of the etl::array. I cannot understand why this is working and why it is compiling at all? And I wonder what type decltype(auto) finally is. I have chosen decltype(auto) because of Scott-Meyers Item 2 and Item 3. To item 3, i am not sure to have a complete understanding on the decltype topic..

When I step through the code it works fine, leaving me pussled behind..

Any help on this topic is highly appreciated!


Thank you very much for your help, it is enlightening to me. Now i finally know why it's working :-D - you made my day!

decltype(auto) is used to determine the type and the value category of an expression. When used as a return type, it lets the function decide what the returned value type should be, based on the expression in the return statement. In this example, since you are using a temporary in the returned expression, it will deduce to an rvalue.

In this declaration:

decltype(auto) x = X(5U);

the syntax is copy-initialization, which has the effect of initializing the variable x from the expression X(5U) . You have a defaulted move-constructor, and the compiler uses this constructor to initialize x from the rvalue returned from X .

Note that from C++17, due to mandatory copy-elision, you could even delete the move constructor, and the code is still valid, since there is no constructor needed to initialize x .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM