tags:

views:

108

answers:

2

IE what happens if you have this following piece of code?

int mean(const vector<int> & data) {
  int res = 0;
  for(size_t i = 0; i< data.size(); i++) {
    res += data[i];
  }
  return res/data.size();
}

vector<int> makeRandomData() {
  vector<int> stuff;
  int numInts = rand()%100;
  for(int i = 0; i< numInts; i++) {
    stuff.push_back(rand()%100);
  }
}

void someRandomFunction() {
  int results = mean(makeRandomData());
}

Am I correct in thinking that C++ will just preserve the newly created object for the life of mean, and then destroy it afterwards since it goes out of scope?

Also, how does this work/interfere with RVO?

Thanks in advance.

EDITED: Added const, forgot to put that in.

+2  A: 

In C++ you can't pass a temporary object to a function that takes a non-constant reference. The example you posted above will not compile. If your compiler compiles it, it is a quirk (extension) of your compiler. If your compiler compiles it without even issuing a diagnostic message, your compiler is broken.

A temporary object (result of your makeRandomData() call), can only be passed to mean through a const-qualified reference. I.e. your mean has to be declared as

int mean(const vector<int> & data) 

in which case the reference will be bound either directly to the temporary object returned by makeRandomData(), or to another copy of that temporary object the compiler might choose to create. (The latter is unlikely in this case, but might happen in theory.)

AndreyT
+8  A: 

My psychic powers tell me that you're compiling this on Visual C++, which is why it even works. In standard C++, you cannot pass an rvalue (which is what the return value of makeRandomData is) to a reference-to-non-const, so the question is moot.

However, the question is still valid if you change the signature of mean to take a const vector<int>&. In which case it all boils down to the lifetime of the temporary - which is defined to last until the end of the "full expression" in which it occurs. In your particular case, the full expression is the entire initializer of results. In case of an expression statement, the full expression is that entire statement.

The Standard does not specify any way in which function arguments can inhibit RVO, but, of course, RVO is a mandate to the compiler to do a particular optimization regardless of visible side effects, not a requirement to do it. When (and if) RVO happens is entirely up to the specific compiler you're using. That said, there does not seem to be any reason why it should be affected by this in any way.

Pavel Minaev
Oh, how did I guess that Visual Studio would be different here...
mathepic
Aha, quirkiness. Thanks for clearing that up a bit. I was indeed doing this in VS, but I forgot to mention the vector was const as well.So to clear things up, if the signature was indeed const, what would be the observable differences between doing this and just passing by value normally? Thanks
Xzhsh
+ 1 for your Psychic Powers!
Kornel Kisielewicz
@Pavel Minaev: I didn't quiet get the 'mandate' vs 'requirement' for the compiler for RVO
Chubsdad
@Xzhsh: the difference would be one extra copy of the vector (the one that it would otherwise have to make for the argument). As written, with references, it will make at most one copy when returning it, and might use NRVO to avoid copying at all, constructing directly into a temporary.
Pavel Minaev
Pavel Minaev