Vector.push_back pass by reference or value?

Pages: 12
Hi guys,

I am pretty new to c++, I am coming from java.

I am having doubts about the function vector.push_back( T& x), in the documentation i am guessing that it is pass by reference because of the argument (T& x) but it doesnt seemed to work for me that way. For instance:


#include "ExObj.h"
#include <vector>
#include <iostream>
using namespace std;
int main() {
vector<Maquina> collect;
Maquina maq1;
Maquina maq2;
//collect.push_back(maq1); <--- Doesnt work, member's value dont change
//collect.push_back(maq2); <----Doesnt work, member value dont change
maq1.createMaquina(1, "Maquina1", "Madrid", 28850);

maq2.createMaquina(1, "Maquina2", "Torrejon", 28850);

maq1.addMarca("Marl");
maq1.addMarca("wins");
maq2.addMarca("fortun");
maq2.addMarca("chester");
collect.push_back(maq1); //<-----this works, when adding to vector after changing value
collect.push_back(maq2); //<-----this works
cout << "Maquina List" << endl;
cout << "size = " << collect.size();
for (int ctr = 0; ctr < collect.size(); ctr++) {

cout << collect[ctr].name << "\t" << collect[ctr].address << endl;
cout << "Number of Marcas: " << collect[ctr].marca.size() << endl;
for (int ctr1 = 0; ctr1 < collect[ctr].marca.size(); ctr1++) {
cout << collect[ctr].marca[ctr1] << endl;
}
}



}

If i would add the Object to the vector before I change some of it's members value, the objects inside the vector, which is supposed to have the same reference, doesnt show the changes when the members are called.
Yes it is correct that the object is passed by reference to the push_back function. Inside the function a copy is made that is stored in the vector.
And that's why adding strings to a vector in C++ is slower than in Java and you can't do much about it. Even if you force it to add pointers to strings, you have to allocate strings on the heap then with new, and it is still much slower than Java, and if you use shared_ptr it is even slower. :P
Last edited on
rapidcoder wrote:
And that's why adding strings to a vector in C++ is slower than in Java and you can't do much about it.


It is always interesting to examine these claims in practice. Given that Java is doing less work you might expect it to be faster. However the actual results can be surprising.

Comparing putting C++ objects into a vector with putting Java references into a Vector is not comparing like for like. However, in my tests, C++ does a great job even though it is doing an awful lot more work:

Comparing C++ copying strings with Java simply storing a reference to the same string:

Java code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.lang.Double;
import java.lang.String;
import java.util.Vector;

class STest
{
	public static void main(String[] args)
	{
		long b, e;

		Vector<String> v = new Vector<String>();
		String s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

		b = System.currentTimeMillis();
	
		for(int i = 0; i < 10000000; ++i)
			v.add(s);
		
		e = System.currentTimeMillis();
	
		System.out.println("Time: " + (new Double((double)(e - b)/1000)).toString());
	}
}


C++ code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <string>
#include <vector>
#include <iostream>
#include <ctime>

int main()
{
	std::clock_t b, e;

	std::vector<std::string> v;
	std::string s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	b = std::clock();
	
	for(size_t i = 0; i < 10000000; ++i)
		v.push_back(s);
		
	e = std::clock();
	
	std::cout << "Time: " << (double(e - b)/CLOCKS_PER_SEC) << '\n';
}


Java
Time: 1.352
Time: 1.177
Time: 1.171
Time: 1.19
Time: 1.17
Ave : 1.212

C++ (unoptimised)
Time: 1.33
Time: 1.32
Time: 1.32
Time: 1.32
Time: 1.32
Ave : 1.322

C++ (optimised)
Time: 0.77
Time: 0.77
Time: 0.77
Time: 0.77
Time: 0.77
Ave : 0.77

Java 8.32% faster than unoptimised C++

Optimised C++ 36.47% faster than Java


Now for Java and C++ doing the same job of storing a reference (pointer) to the same string:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <string>
#include <vector>
#include <iostream>
#include <ctime>

int main()
{
	std::clock_t b, e;

	std::vector<std::string*> v;
	std::string s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

	b = std::clock();
	
	for(size_t i = 0; i < 10000000; ++i)
		v.push_back(&s);
		
	e = std::clock();
	
	std::cout << "Time: " << (double(e - b)/CLOCKS_PER_SEC) << '\n';
}


C++ (unoptimised)
Time: 0.58
Time: 0.59
Time: 0.59
Time: 0.59
Time: 0.59
Ave : 0.588

C++ (optimised)
Time: 0.42
Time: 0.41
Time: 0.42
Time: 0.42
Time: 0.42
Ave : 0.418

Unoptimised C++ 51.49% faster than Java
Optimised C++ 65.51% faster than Java


These are very simple tests that do not reflect the behaviour of real world applications.

Well, the results greatly depend on the C++ compiler, standard library implementation and Java implementation.
With GCC 4.6 and OpenJDK 6b22 I get:

(all C++ tests are with wstring)

Java (ArrayList): 0.19s
C++ (value): 0.31s
C++ (pointer): 0.18s

Edit: of course, vector usually isn't the preferred container anyway when dealing with a large number of objects:
C++ (deque, value): 0.15s
C++ (deque, pointer): 0.07s
Last edited on
1. Java (possibly on Windows, right?) without -server flag is like gcc without any optimisation.
2. Vector?!!! Man, are you kidding? Add mutex_lock / unlock into your C++ loop and *then* compare. Java's Vector is thread safe, C++ vector is not. Or better use ArrayList.
3. Test running for a less than 1 second on an outdated Java means nothing.

To summarise: double triple facepalm.

Other flaws:

4. Storing a raw pointer to a string in a std::vector is a bad idea for many reasons. This is a bug waiting to happen, because strings are mutable and additionally, who is the owner? The container? If so, who is gonna delete them? What if your container needs to live longer than the current scope the string is in? Therefore modern C++ programmers advocate using shared_ptr. ;)
5. C++ strings don't support unicode, you should use wide strings to make these tests comparable. This is however important in value test only, which C++ lost anyway *even using short strings*, at least in the Athar's test.


----------------------------------------------
Java code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import java.lang.Double;
import java.lang.String;
import java.util.List;
import java.util.ArrayList;

class VectorTest {

  private static void test() {
    final int COUNT = 1000000;
    List<String> v = new ArrayList<String>(COUNT);		
    String s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for(int i = 0; i < COUNT; ++i)
        v.add(s);
  }

  public static void main(String[] args)	{		
      long b = System.currentTimeMillis();
	
      for (int i = 0; i < 1000; ++i)
	  test();
		
      long e = System.currentTimeMillis();	
      System.out.println("Time: " + (e - b) / 1000.0);
   }
}


Equivalent C++ code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <vector>
#include <string>
#include <memory>
#include <ctime>
#include <iostream>

void test() {
  const int COUNT = 1000000;
  std::vector<std::shared_ptr<std::string> > v;
  v.reserve(COUNT);
  std::shared_ptr<std::string> sp(new std::string("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"));
  for(size_t i = 0; i < COUNT; ++i)
	v.push_back(sp);
}

int main() {

        std::clock_t b, e;
	b = std::clock();
	
	for (int i = 0; i < 1000; ++i)
	  test();	
		
	e = std::clock();
	
	std::cout << "Time: " << (double(e - b)/CLOCKS_PER_SEC) << '\n'; 
        return 0;
}


Options and versions:
C++ - gcc 4.6.1, 64bit, optimisation level -O3 (checked also -O2, but no huge difference)
Java 6 update 30, 64 bit, -server (not really needed, because on ubuntu it defaults to -server)

And now the timings:
C++: 6.07 s
Java: 2.59 s

Without reserving space and just letting the vectors grow as more elements are added:
C++: 21.07 s
Java: 4.81 s (4.51 s when used -XX:+UseCompressedOops optimisation)

Ok, you may point out, that shared_ptr is not fair, because *sometimes* you know your string will outlive the container, and you can use your raw pointers. Ok, so with raw pointers (just used std::string* instead of shared_ptr):

C++ with space reservation: 2.65 s
C++ without space reservation: 9.12 s

So to conclude: C++ matched Java performance only once in this test, and had to use non-garbage collected, raw pointers and had to specify the vector size in advance. In all other cases, Java was 2-4x faster. Reasons are simple:

1. In Java raw pointers are both *better* in terms of functionality and *much faster* than shared_ptrs in C++.
2. In Java memory allocation / reallocation is much faster (the test without prior reserve shows it cleanly).

Last edited on
I would dare you to turn off exceptions on c++, which are bulky constructs just like a shared_ptr. Do a Sizeof Operator on a shared_ptr to a normal pointer and you will see what I mean. A comparison like you are doing between a language which has garbage collection and one that doesn't isn't fair.
Yeah, this is a typical answer of most diehard C++ coders I expected, after posting a Java-faster-than-C++ benchmark. Don't use virtual calls, don't use dynamic casts, don't use exceptions, don't use STL, use raw pointers, raw arrays, raw procedures, provide your own memory allocators and do everything in a one big cpp/header file to allow everything inline. This is probably what most of C++ vs <put any language here> benchmarks do.

Well, I agree this can lead to outperforming just any language possible, maybe except hand optimized assembly. I totally agree, you can't beat low level C++ in Java in many cases, at least not now. Still JVM is lacking some important performance features, e.g. value types, object inlining (no, not method inlining, which JVM is very good at) or dynamic call specialization. I hope they will work them on in a few years; the only limit is human resources - someone has to do that.

In real programming you *do* use exceptions, you *do* use containers, you *do* use inheritance and virtual dispatch, you *do* use objects with shared ownership, you *do* use abstractions etc. And in such cases, although it pretty is often argued C++ is good enough (called sometimes high-level C++ or modern C++), and whoa, it can even do "almost automated" memory management, it is not really faster than Java. Simply - it is either fast or high level but not both at the same time.

Want me to compare uncontended synchronized vector appending in C++ or Java? Multicore is the future, so such test would be quite interesting... Oh, don't worry, I won't enable -XX:+DoEscapeAnalysis -XX:+EliminateLocks and -XX:+UseBiasedLocking, to give C++ some chances...

As for shared_ptr - yeah, I know, they are bigger. So what? They have to be bigger, otherwise they would not be possible. They are bigger, slower and offer less than proper GC, which you can't have in C++.


A comparison like you are doing between a language which has garbage collection and one that doesn't isn't fair


Of course it is not fair. The GCed language has to GC. It has more work to do to find the regions of free memory, while the non GCed language is given it in the code. So the GCed language should be obviously slower. :D
Last edited on
I don't think all this bizarre trolling is fair to the original poster who was simply confused by the unfamiliar concept of pass-by-reference.
This is just an illustration on how pass-by-reference or pass-by-pointer does not always do what you may think. The original poster was not confused by pass-by-reference but by the behaviour of STL container that copies data internally. If he passed by value, two copies would be made instead of one, which is even worse. STL containers are value-based, Java containers are pointer-based. This makes a huge difference in how you use them and has a big impact on their performance.

And you call it trolling, because it doesn't fit the image of the world you have, in which *everything* in C++ is much much faster than Java (while the truth is that most of the things are just the same, some things are faster in C++ and other things are faster in Java). But it is always easier to attack the person than the claim, so I understand.
Last edited on
rapidcoder wrote:
Don't use virtual calls, don't use dynamic casts, don't use exceptions, don't use STL, use raw pointers, raw arrays, raw procedures, provide your own memory allocators


Are you essentially saying "use C over C++"?
C++ is faster than Java at everything, real programmers know that. And neither of these test are professional tests. Newbies...
Don't use virtual calls, don't use dynamic casts, don't use exceptions, don't use STL, use raw pointers, raw arrays, raw procedures, provide your own memory allocators


This sounds like the days before the STL, in other words when Bjarne Stroustrup was quoted "C++ is batteries are not included".

Are you essentially saying "use C over C++"?


No, but if you need raw speed, use something very close to C. C++ is sometimes faster than C, e.g. where you can use templates instead of function pointers. I'm only saying you should know your tools and be careful. Simple assumptions like language X is always faster than language Y don't work in this world.


C++ is faster than Java at everything, real programmers know that. And neither of these test are professional tests. Newbies.


Yawn. Show me your "professional test" proving appending vectors in C++ is faster than in Java.
Yawn. Show me your "professional test" proving appending vectors in C++ is faster than in Java.


Nah man, it would require me to write too much code. I don't have the time right now.

A programming language can't be tested that way, because you don't use it that way. The platform where it runs is also important. There is a loooot of factors to take into account.

Java is a really good programming language, there are some fields where it looks it's faster than native languages like C/C++, when doing these tests. But in the long run, with more complicated applications and going more twisted, you will release that C++ is faster than Java, at everything.

When programming simple applications Java is the best programming language, but if someday you want to make a very big application, please don't use it, your users will be happy.

But in the long run, with more complicated applications and going more twisted, you will release that C++ is faster than Java, at everything


Engineers at big companies realized just the opposite. Twitter, Amazon, Google, Facebook, LinkedIn, Reddit, Netflix and other must be extremely stupid, because they have written their *performance critical big applications* in Java (and this is including low-level database and messaging stuff - yeah).


When programming simple applications Java is the best programming language


Totally wrong. Java is terrible at simple applications, because of the obvious JVM, memory and startup overhead. I can't imagine unix tools like mv, rm or echo written in Java. It would take more time to start than to do actual work. Java rocks for long running, big, distributed server apps serving millions of users.
Last edited on
Well, I don't want to start a discussion here, I don't have the time as I said before. But ask those company if they really are using Java for the "performance critical big applications" (I wouldn't consider low-level data-base programming a big application, but whatever) considering really performance, or if they are doing it for money/productivity reasons, you'll get the answer.

Now go to Ubisoft, Eidos, EA, Activision, and ask them what they use to program their games. If Java were so fast an cool as you say, everybody would be using it for everything. But every programming languages have their disadvantages and advantages, and the slowness disadvantage is very far from C++. If you're a Java fanboy, fine. Maybe around your environment Java is just the best options. But believe me, I would like to use Java to make my games, but its limitations doesn't allow me to do it.

Maybe when computer get more powerful and cheaper, Java will be fine. But now to optimize my game to run in a big series of different PCs, I need something better (in the performance scene).
Game industry has always been the most conservative one. They used assembly when everyone else used C (yeah, and claimed C was slow). They used C when everyone else used C++. Now they use C++ (not everywhere) where almost everyone uses Java/C#. See a pattern here? And don't forget the game market is not only AAA PC or console games. There is a huge market for mobile / web games / indie games, and they are not written in C++. Some of these games (e.g. Minecraft or Farmville) made more revenue than the most successful AAA games written in C++ (and Zynga is currently worth more than EA). Additionally the market for PC and console games is slowly dying.


But ask those company if they really are using Java for the "performance critical big applications"


Database *engine* is a performance critical component for an application that handles over 1 million writes *per second* (Netflix) or stores petabytes of data (Facebook) or requires millions of messages being passed per second (Twitter).
Last edited on
rapidcoder wrote:
Engineers at big companies realized just the opposite. Twitter, Amazon, Google, Facebook, LinkedIn, Reddit, Netflix and other must be extremely stupid, because they have written their *performance critical big applications* in Java (and this is including low-level database and messaging stuff - yeah).
AMCerasoli wrote:
But ask those company if they really are using Java for the "performance critical big applications"
rapidcoder wrote:
Database *engine* is a performance critical component...
I think he was suggesting that he does not believe that Java is used for the "performance critical big applications" rather than say that there applications are not performance critical.

Would you care to site your source(s) for the claims that those companies use Java in the performance critical areas?
Last edited on
Game industry has always been the most conservative one. They used assembly when everyone else used C


See a pattern here?


Of course I do... And you are giving me the reason. By the time C was invented, wasn't enough fast to make videogames (among other things), the same is happening now... Java is not improving, what is improving is the hardware. Maybe when we have a 16 cores CPU and a 32 cores GPU, Java will be like C++, and using C++ will be pointless, but now isn't enough.

The unique reason big companies are using Java developers currently is because of money and productivity, and because computer are getting more powerful and you can't notice the difference in most of the case when programming user interfaces, database, and other stuff.

There is a huge market for mobile / web games / indie games, and they are not written in C++.


That's true, I haven't say the contrary.

Some of these games (e.g. Minecraft or Farmville) made more revenue than the most successful AAA games written in C++ (and Zynga is currently worth more than EA).


That's also true. But I think we're not talking about marketing here.

Additionally the market for PC and console games is slowly dying.


Ups... There you failed... Maybe consoles, but PC... Never.

Database *engine* is a performance critical component for an application that handles over 1 million writes *per second* (Netflix) or stores petabytes of data (Facebook) or requires millions of messages being passed per second (Twitter).


Aha... And you thing they're handling all that in just one computer/server... With a beautiful JVM pretty smooth and nice... Come on man... You wouldn't do that not even with C++.

Let me go to Google and offer them a real, low-level performance critical software to handle data-bases, using C++ and OpenCL, and they'll see how can I do the same they do with 3 PC with just one...
Pages: 12