home bbs files messages ]

Forums before death by AOL, social media and spammers... "We can't have nice things"

   comp.lang.c++.moderated      Moderated discussion of C++ superhackery      33,346 messages   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]

   Message 32,593 of 33,346   
   =?UTF-8?B?RGFuaWVsIEtyw7xnbGVy?= to Edward Rosten   
   Re: Move, std::vector and gcc: which is    
   18 Oct 12 06:16:45   
   
   From: daniel.kruegler@googlemail.com   
      
   On 2012-10-18 01:25, Edward Rosten wrote:   
   > I have a simple program below which defines or defaults various   
   > combinations of move and copy constructors and puts the classes into a   
   > std::vector.   
      
   [snip]   
      
   > This is what I expected. When the vector resizes itself, the move   
   > constructor is always called. In the final case, this is implied by the   
   > copy constructor not being called.   
      
   [snip]   
      
   > In other words, when both copy and move are defined explicitly, the copy   
   > constructor gets called but if the move constructor is defaulted, then it   
   > gets called in preference to the copy constructor.   
   >   
   > I would have expected the GCC 4.6 behaviour to be correct. Am I mistaken?   
      
   You are mistaken. Let me explain a bit the reasoning of my assertion:   
      
   Originally move construction was considered as a "must-be-nothrow"   
   operation in the library, but during the standardization process several   
   good reasons were brought on the table that argued in favour for   
   allowing potentially throwing move-operations. Potentially throwing   
   move-operations were the main reason why noexcept was invented as both   
   deduction mechanism and exception-specifier. A fundamental difference of   
   move operations versus copy operations is that the former can   
   irreversibly change the state of the *source* of the move. This would   
   mean that a throwing move prevents that an operation can hold the strong   
   exception guarantee, that is, either the operation has succeeded or   
   there are no effects.   
      
   If you look at the specification of vector's push_back (and some other   
   insertion operations) you find the following specification:   
      
   "If an exception is thrown other than by the copy constructor, move   
   constructor, assignment operator, or move assignment operator   
   of T or by any InputIterator operation there are no effects. If an   
   exception is thrown by the move constructor of a non-CopyInsertable T,   
   the effects are unspecified."   
      
   So for every type that has a copy constructor (using the   
   std::allocator), the standard requires that vector's push_back either   
   succeeds or has no effects. If your type has a potentially throwing move   
   constructor (This is so in your example), it has to fall-back to a copy   
   operation when it can. If there is no copy possible, there is no more   
   the guarantee that this operation has the strong exception guarantee.   
   This explains why gcc 4.7 correctly falls back to copy operations for   
   type Both (The first move can be done safely, because it does not affect   
   the existing container elements), because it has a potentially throwing   
   move constructor and an accessible copy constructor. For a move-only   
   type an implementation is no longer bound to the "no-effects-on-failure"   
   constraint (It would be impossible to realize that), therefore uses the   
   move constructor irrespective whether it could throw an exception or not.   
      
   There is a simple way to realize that only your move-operations are   
   called instead of copy operations for type Both: Ensure that the move   
   constructor does not throw operations and mark it with the equivalent of   
   noexcept(true) or throw().   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
         [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
         [ comp.lang.c++.moderated.    First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   

[   << oldest   |   < older   |   list   |   newer >   |   newest >>   ]


(c) 1994,  bbs@darkrealms.ca