Subject: Prosper advance, No.3457345

From: Prosper Advance <[email-masked]>
Date: Thu, 18 Sep 2014 10:25:21 -0700

Date: September 18, 2014
Re: Personal Advance
Amt: 2,000 - 35,000
Ref-id: 846-972415

------

Looking for a financial kickstart?

~Start your small business.
~Pay off your debt.
~Time to start that home improvement project you have been dreaming about?

Select your amount: http://www.suqta.com/adv-type-1/se/873-index.hmtl
-------

Check your rate in minutes and watch yourLoan get funded in as few as three days. It's that easy.

-----
-----
Home > FAQ > About Us

From: ADA FIN Networks 2014.
[12036 Legion Place]
[Philadelphia, PA]

(Redact yourself from future messages if you would like to stop them - http://www.suqta.com/re/re)

,
,
,
,
,
,
,
,
,
,

Re: Food Left Out, Spoilage concern

 I forgot to put the freshly made pot of stew in the fridge last night. I woke up and found it still sitting in the cool kitchen (I was waiting for it to cool down). Of course I immediately placed it in the fridge. (I have a fridge thermometer and so my fridge is always kept at the right temp). It is just some cooked stewing steak (beef) with lots of cooked veg in a thick gravy. 
http://www.govloans.gov/about-us
I have lost my sense of smell so am a bit nervous about detecting whether it will be safe to heat up today. I think it should be OK as the meat has been cooked.

Do members think it will be safe to heat up and eat this evening?
Note, the operand of decltype does not need to have an accessible destructor, i.e. it is not semantically checked as a full-expression.

template< typename t >
t declprval() noexcept;
http://www.govloans.gov/news/news-article-archive/news-article/827
class c { ~ c (); };
decltype ( declprval< c >() ) * p = nullptr; // OK

Suppose I have the following code:

int main()
{
    std::vector<std::string> strs;

    std::string var("Hello World");
    // Make some modifications to 'var'
    strs.push_back(std::move(var));
}
The part of the sample I want to point out is the usage of std::move(). Basically I'm worried about a copy on the push_back() call. Suppose the string I'm adding is really big. I'm still learning C++11 r-value references, so I'm not sure how the compiler would optimize away the copy (if at all) without the std::move().

Could anyone explain if this is a premature optimization (forcing moves in all cases where you want to avoid copies, in general)? If so, what patterns should I expect the compiler to follow (or most likely follow) that would result in an optimized and automatic move here?

EDIT
I want to add that I understand how automatic moves happen on function return values, because NRVO/RVO applies. The specific example I gave here wouldn't apply RVO, so I'm uncertain.

c++ c++11
share|improve this question
edited Aug 27 at 14:21

asked Aug 27 at 14:16

void.pointer
3,54142671
  	 	
move really only makes sense if the function called is let's say move aware (and the type supports move semantics.) In this case, the function you are calling is not, and so you will gain nothing from this. If however you were calling a move aware function (say emplace_back()), then it makes sense to use std::move(). Same principle applies to any of your custom functions, types etc.   Nim Aug 27 at 14:39
  	 	
@Nim is that necessarily true? I was considering a scenario where a temporary is move-constructed (from the forced r-value returned by std::move), and then that would be passed into push_back() as an r-value (const ref). Is this scenario wrong?   void.pointer Aug 27 at 14:44
6	 	
@Nim Since when is push_back not move-aware?   T.C. Aug 27 at 14:45 
1	 	
@Nim Also push_back has an overload for r-value reference (although I'm not sure it matters for this specific example): en.cppreference.com/w/cpp/container/vector/push_back   void.pointer Aug 27 at 14:47 
  	 	
aargh, my bad, take my second comment in the context of a general move aware function, I removed my earlier comment (can't edit the one above..)   Nim Aug 27 at 15:00 
show 1 more comment
5 Answers
activeoldestvotes
up vote
16
down vote
accepted
The other answers focus too much on the technical aspects of the question for my taste, so I will try to give a more general answer.

In short: No, using a "trick" like std::move in the way it's described in the question isn't a premature optimization. Not using std::move when it can be used is fine too, unless the code is already known to be performance critical.

The need to avoid premature optimization is sometimes understood as "don't optimize, until you can prove it's necessary", but I prefer to read it as: "don't waste time solving problems unless you know they need to be solved".

Premature optimizations require spending effort in order to optimize what may not need to be optimized, and usually transform a simple problem into a complex problem while doing so. From that perspective, I would classify any long pondering of the question itself as premature optimization.

A related example: People working in performance critical code will often pass arguments as const references ( const std::string& ). Because that's what they are used to do, they will use the same pattern in code that isn't performance critical, even tough they could just use pass-by-copy ( const std::string, or even std::string ). That isn't a premature optimization either.

share|improve this answer
edited Sep 5 at 18:31

answered Aug 27 at 19:25

Peter
1,703220
7	 	
+1: From that perspective, I would classify any long pondering of the question itself as premature optimization. If unconditionally using a fast approach is easier than determining whether a slow approach would also work, then unless one has reason to believe that some theoretical advantage of the slow approach might be important, ascertaining whether one could use the slow approach to leave open its theoretical advantages could represent a different form of "premature optimization" [not for speed, but potential flexibility].   supercat Aug 27 at 21:06
1	 	
I agree in this case. The one count against this is that moving from var might make it somewhat harder for readers of the code to reason about the state of var. The same is true of anything that mutates var, of course, doing so via the result of move isn't special. But if using move causes you to not mark some object const that otherwise could be, then you might get into an area where the possibility of a speed-up is less value than keeping things conceptually simple (assuming immutable values are simpler, which I claim is often true).   Steve Jessop Aug 28 at 11:33 
  	 	
@SteveJessop Agreed. While std::move adds a declaration of intent, and a possible optimization, there are many variations of the example where std::move can add unnecessary confusion, complexity, and/or risk. In the end, r-value programming is a learned skill just like const correct programming.   Peter Aug 28 at 11:54
1	 	
@Peter Concerning your last paragraph, passing by const reference when you do not need to mutate the object is a good best practice, regardless of the importance of performance at that site. This would basically start a discussion on premature pessimization which I won't go into, but it almost sounds like you're saying that passing a vector in as a copy (example) when it won't be modified is acceptable practice. I don't necessarily agree with that. Correct me if I've misunderstood.   void.pointer Sep 5 at 17:34
1	 	
It was a tough call but I'm marking this one as the answer despite the fact that it does not have the most upvotes. The highest voted answer certainly answers the question, however I feel like after reading everything, I get the most takeaway value from this one. Not only does this address my concern with premature optimization with std::move, but it provides good general outlook that can be applied elsewhere. Also the comments/discussion here adds a lot of helpfulness/value as well. Thanks to everyone for your contributions and thought.   void.pointer Sep 5 at 18:09
show 1 more comment

up vote
25
down vote
I'm not sure how the compiler would optimize away the copy (if at all) without the std::move().

Only a very clever compiler could optimise that away, so if the copy could be expensive (e.g. a very long string) then it is better to move it.

Without the move the code is effectively a sequences of calls to:

strlen  // count "Hello World"
malloc  // allocate memory for string var
strcpy  // copy data into var
malloc  // re-allocate vector
free    // deallocate old vector
malloc  // allocate new string
strcpy  // copy from var to new string
free    // destroy var
With the move it becomes:

strlen  // count "Hello World"
malloc  // allocate memory for string var
strcpy  // copy data into var
malloc  // re-allocate vector
free    // deallocate old vector
In theory a smart compiler could do that transformation automatically, but for the compiler to see through all the layers of abstraction introduced by the constructors and destructor and the vector member functions is quite difficult, so proving that the code could be transformed to remove a malloc and free is complicated.

share|improve this answer
edited Aug 27 at 15:46

answered Aug 27 at 15:25

Jonathan Wakely
49.5k272151
add a comment
up vote
20
down vote
After std::move, the original object, in this case var, must be in a valid state but could hold any value, e.g. it might be empty.

If you know you are not going to use var and you only created it to put into the vector then it isn't really "premature" optimisation as the intention of what you are trying to do.

vector has a new method emplace_back() which is the same thing but clearer, and uses forward-arguments (here you just do emplace_back("Hello World") if all you are doing is constructing it). In your case as you are "making some modifications with var" emplace_back isn't likely to not be appropriate.

In old C++ you could optimise the copy by doing push_back() on an empty string then swapping it.

share|improve this answer
edited Aug 27 at 16:00

answered Aug 27 at 14:24

CashCow
19.7k22147
  	 	
Before emplace_back was introduced, how would you implement the same functionality, i.e. resize and construct in place? I guess that mechanism is different than std::move.   mostruash Aug 27 at 14:39
  	 	
The compiler should know when a variable is not used anymore especially in this simple case and just insert the move or even construct the string directly inside the vector. Therefore one could argue that this micro optimization should not be done manually.   nwp Aug 27 at 14:39
1	 	
@nwp - How could the compiler do that in the general case? We know how string behaves, but how could the compiler know that, e.g., var's destructor won't have different behavior depending on whether or not it was moved?   Josh Kelley Aug 27 at 15:17
  	 	
@JoshKelley By looking at the implementation of the move constructor and destructor. There are edge cases where the compiler cannot know for sure but 99.9% of the cases are obvious. That said I believe compilers are not smart enough yet so manual move is the way to go for now.   nwp Aug 27 at 15:33 
1	 	
@nwp, the compiler would not look at the move constructor. Optimizers do not look at the source code of other functions and see if they are equivalent and could be used instead, the optimizer would work at a lower level (the compiler's AST or similar) and see that malloc+memcpy+malloc+memcpy+free can be transformed to just a malloc+memcpy, which would have the effect of constructing the string directly in the vector   Jonathan Wakely Aug 27 at 15:52 
show 3 more comments
up vote
15
down vote
I don't know why everyone is suggesting you use emplace_back(). The purpose of emplace_back() is to avoid copy/move operations by constructing the object in place. In this case, you have already constructed the object, so at least 1 copy/move is unavoidable. There is no advantage to using emplace_back() over push_back() in this case.

Otherwise, I agree with everyone else saying that it's not a premature optimization because the move semantics models what you are trying to do more closely than making a copy of the object.

share|improve this answer
edited Aug 27 at 15:23

answered Aug 27 at 15:13

Paul
1635
1	 	
Not sure why you only have my upvote - this is a good answer IMHO. The // Make some modifications to 'var' part of the OP makes emplace_back useless here.   Jonathan Wakely Aug 27 at 17:59 
  	 	
@JonathanWakely: But one can use emplace_back to construct and append a new string in-place, call back() to get the reference to the newly created string and modifies it then.   C.R. Aug 28 at 7:30
  	 	
@C.R: you can, although that trick often makes it harder for your code to implement the strong exception guarantee when acting on an externally-visible vector. If the modification to the string fails (in particular throws) then you need to undo the emplace_back change you already made. Of course, when the vector is local there's no such problem, but I think it means people tend to ignore the trick rather than worry about whether it's safe in context. In practice it's less dangerous than people might think, since use of anything_back commonly does several such, so needs attention already.   Steve Jessop Aug 28 at 11:39 
  	 	
@C.R. I generally like to avoid "cute" stuff like that, it violates the KISS principle. I like to keep code simple, natural, and self-documenting as a first priority. If it becomes a bottleneck based on real measurements, then I will consider "tricks". But it doesn't make sense to use them right away.   void.pointer Sep 2 at 16:23 
1	 	
I think this should rather be a comment under an answer or a suggestion to an answerer rather a stand-alone answer.   me how Sep 4 at 10:39
show 1 more comment
up vote
1
down vote
Yes, it is premature optimization if it is premature optimization.

Let me elaborate:
Premature optimization is defined by whether you are optimizing a part of the code that you don't know to be performance critical. That is, premature optimization is never defined by the method of optimization, it is always defined by the place of optimization and your knowledge about what you are doing.

Now, to the advisability to optimize using std::move():

With std::move() you avoid the heavy lifting of copy construction, like memory allocation, deallocation, copy constructing contained elements, deconstructing contained elements, etc. That is good. But one part remeains: the construction/destruction of the container object.

emplace_back() has the virtue of entirely avoiding the construction of the temporary object. So, whenever you can avoid a temporary object by using emplace_back(), you have a small win.

Considering code quality (read readability/maintainability): std::move() has the downside of leaving you with an unusable object, which can be a source of bugs. This does not happen with emplace_back(). So, again, the later is clearly preferable.

Of course, emplace_back() cannot be used in all contexts that allow the use of std::move(). So, if these are performance critical, std::move() may be the way to go. There are some very valid use-cases for optimization with std::move(). However, you might also find out that you can write the code in a way that does not require any copy/move/emplace construction at all. Never stop looking for a better solution when optimizing!

In the end, it remains that the validity of optimizing with std::move() depends entirely on the context: It is good optimization wherever it is good optimization.

share|improve this answer
answered Aug 27 at 15:46

cmaster
8,0592830
7	 	
The tautologies are just noise.   nwp Aug 27 at 16:11
  	 	
premature optimization is doing something non-intuitive that doesn't show intent and you wouldn't normally want to do but you think it will make the code faster or optimal in memory usage etc.   CashCow Aug 27 at 16:40
  	 	
vector<bool> is a clear case of premature optimization, trying to optimize is memory-use..   CashCow Aug 27 at 16:41
  	 	
@CashCow vector<bool> can well make the difference between a running program, and a program that becomes victim to the OOM-killer. Also, it can well make the difference between a runtime of 1 or 32 seconds. However, it depends entirely on the use-case whether vector<bool> is an optimization or not. In most programs that use vector<bool> it will be premature optimization. But vector<bool> is a special case: it's within a library, and libraries must be optimized for all relevant use cases (if they are optimized at all). And a factor of 32 is too big an optimization to pass by.   cmaster Aug 27 at 16:51
5	 	
@cmaster: your comment already contains the reason why vector<bool> is extremely bad - with "bad" beeing: that this tradeoff is forced on every user of std::vector, whether they like it or not. The optimization in vector<bool> is undoubtedly important, but simply presented under the wrong name! A better (and consistent) name would be something along the lines of dynamic_bitset   MFH Aug 27 at 16:56