0

I have a class that contains a vector<vector<int>> adjacencyLists;

Which is more commonly used to initialize a vector of vectors ?

1)

adjacencyLists = vector<vector<int>>(vertices, vector<int>());

2)

vector<vector<int>> adjacencyLists(vertices, vector<int>());

I personally find the 1st to be more clear because of the = sign, but I get a feeling that people use the 2nd more often, is this true ?

dimitris93
  • 4,155
  • 11
  • 50
  • 86
  • Is it an in-class initializer/member init-list/constructor body operation? Also, the temporary `vector()` isn't necessary. – Weak to Enuma Elish Feb 26 '16 at 21:14
  • @JamesRoot It is a private variable of a class named `Graph` and I am initializing it on the constructor – dimitris93 Feb 26 '16 at 21:14
  • 2
    Is there a reason you chose `vector` specifically for your question? This could apply to any class (e.g., `A a = A(blah);` vs. `A a(blah);`, where `A` is an arbitrary class), correct? – R_Kapp Feb 26 '16 at 21:15
  • @R_Kapp I am not familiar with the c++ syntax and conventions, I am trying to figure it out. – dimitris93 Feb 26 '16 at 21:16
  • @JamesRoot Are you sure that `vector()` is not necessary ? That way I won't be initializing the inner vectors though. No ? – dimitris93 Feb 26 '16 at 21:17
  • 1
    @Shiro If you don't pass an instance to copy construct from, it just default constructs them. – Weak to Enuma Elish Feb 26 '16 at 21:18
  • Off topic: It looks like you are building a graph. Smurf, I sound like a paper clip. Anyway, odds are pretty good that you want this to be fairly zippy, move at a good clippy I should probably have worded it, and vector of vector has some nasty performance holes due to a lack of spatial locality. Give this question and answer a read for a better way: http://stackoverflow.com/questions/34077816/how-to-properly-work-with-dynamically-allocated-multi-dimensional-arrays-in-c – user4581301 Feb 26 '16 at 22:45

3 Answers3

2

The first version creates an object and then assigns it to a variable.

The second one only creates an object. So it could theoretically be more efficient, however I am pretty sure that most compilers will create the same code in both cases.

Frank Puffer
  • 8,135
  • 2
  • 20
  • 45
2

Given that the vector is a class member, you're better off using an initialiser list

 YourClass::YourClass(std::size_t vertices) : adjacencyList(vertices, std::vector<int>())
 {

 }

since it invokes the constructor for the vector<vector<int> > directly.

Doing assignment

 YourClass::YourClass(std::size_t vertices)
 {
     adjacencyList = vector<vector<int> >(vertices, vector<int>());
 }

is actually functionally equivalent to

 YourClass::YourClass(std::size_t vertices) : adjacencyList()
 {
        adjacencyList = vector<vector<int> >(vertices, vector<int>());
 }

since all members and bases are implicitly constructed before entering the body of YourClass::YourClass. (The standard has rules for order of construction of multiple bases and members, but the result is still the same).

This means your approach constructs adjacencyList, creates a temporary vector<vector<int> >, and invokes the assignment operator to effectively reinitialise adjacencyList. The best case (assuming vectors constructors and operators are sanely implemented, which most are) is that this approach has no more overhead than initialising directly. The worst case, since it is constructing more temporary objects and the compiler might not optimise them out of existence, is greater overhead.

Peter
  • 35,646
  • 4
  • 32
  • 74
0
class test
{
public:
    // The good thing about this is that it will always work
    // even if you have multiple constructors.
    vector<vector<int>> adjacencyLists { vertices };

    // Unlike this:
    test() : adjacencyLists  { vertices}
    {

    }

    test()
    {
        // This is calling the move assignment operator.
        // 1) adjacencyLists empty vector was created earlier.
        // 2) Temporary vector { vertices } is created.
        // 3) Temporary vector is moved to the adjacencyLists  vector.
        // 2 constructor calls, and 1 move assignment call.
        adjacencyLists = decltype(adjacencyLists) { vertices };

        // Using the member initializer list or
        // using a default member initializer or
        // using resize only construct a single vector.
    }

    test()
    {
        // This would be what you are looking for instead
        adjacencyLists.resize(vertices);
    }    
};
Jts
  • 3,447
  • 1
  • 11
  • 14