How to provide forced copy, why it will not work with the remote copy constructor?

I have a non-dangerous class. Copying this would be problematic. I want to guarantee that it will never be copied, so I made its copy constructor deleted :

 class A { public: A(); A(const A&) = delete; }; A fun() { return A(); }; int main() { A a = fun(); }; 

Unfortunately, g ++ does not compile this for a reason:

 t.cc: In function 'A fun()': t.cc:8:12: error: use of deleted function 'A::A(const A&)' return A(); ^ t.cc:4:5: note: declared here A(const A&) = delete; ^ t.cc: In function 'int main()': t.cc:12:13: error: use of deleted function 'A::A(const A&)' A a = fun(); ^ t.cc:4:5: note: declared here A(const A&) = delete; ^ 

But this is a very clear situation when you need to use copy, so the copy constructor should never be called. Why is this so?

+7
c ++ c ++ 11 copy-elision
source share
3 answers

As long as C ++ 17 copy elision is not an optimization, the compiler should not execute, so classes should be copied because the compiler may want to copy (even if it is not really so). In C ++ 17, in many cases copying will be guaranteed, and then classes will not need to copy ctors.

See also:

http://en.cppreference.com/w/cpp/language/copy_elision

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/ (bit about "Guaranteed copying of text")

Perhaps you can use the old copy constructor declaration trick in your class, but don't really implement it? The compiler should like this if it does not actually call a copy of ctor. I have not tested this, but I believe that it should work for your case until C ++ 17 appears.

+9
source share

You cannot force copy (yet) (see other answers).

However, you can provide a default move constructor for your class, this will move (and therefore not copy) the return value if RVO / NRVO is not possible. To do this, you must add = default for your move constructors:

 class A { public: A() = default; A(const A&) = delete; A(A&&) = default; A& operator=(A&&) = default; }; 

Example

+8
source share

Optimizing the return value (RVO and NRVO) does not mean that the types associated with the ability to copy or move are discarded. This requirement applies whether you receive an RVO or not.

The most likely reason is that copying is not performed (currently). This is an optimization that may take place, and it would be inappropriate to compile or not use the code based on whether this optimization is used in a particular implementation.

In C ++ 17, RVO will be applied in some cases, and the requirements for copying and moving will be removed.

+7
source share

All Articles