7

I am using an STL vector that is a vector of Parameters.

std::vector<Parameter> foo;

I was trying to find a way to add Parameter objects to the vector without doing this:

Parameter a;
foo.push_back(a);

I came across an implementation that did this:

foo.push_back(Parameter()); //Using the Parameter constructor

I thought that when I created an object the constructor is called not vise versa. Why can I pass a constructor to a function?

larrylampco
  • 597
  • 1
  • 9
  • 33

6 Answers6

8

foo.push_back(Parameter()); is passing a temporarily constructed Parameter object to push_back and not the constructor i.e. Parameter() is a call to create an object of type Parameter on the stack and pass it to the push_back function of vector, where it gets moved/copied. Thus what gets passed is not the constructor itself, but a constructed object only.

It's just a shorthand way of writing Parameter a; foo.push_back(a); when one is sure that a is not used anywhere down the line; instead of declaring a dummy, temporary variable, an anonymous temporary is created and passed.

These might be useful if you want to learn more about temporaries:

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=198

http://msdn.microsoft.com/en-us/library/a8kfxa78%28v=vs.80%29.aspx

legends2k
  • 31,634
  • 25
  • 118
  • 222
  • 1
    It's actually not only a shorthand, though. The semantics of the program differ in both variants. When passing an anonymous object, the object gets destroyed at the end of the expression. But when declaring a variable, the lifetime is extended to the end of the scope. – Sebastian Mach Jun 19 '13 at 14:55
  • @phresnel: Yes, from a compiler's (pedantic) viewpoint one can take the address of `a` since it's an L-value; I meant from the programmer's standpoint when s/he writes it this way, it usually is done to avoid giving it a name. – legends2k Jun 19 '13 at 14:59
  • Or to make sure there's no waste or resources kept open for a longer time than necessary. Being inprecise can even be disastrous. Imagine you pass some database connection to a function, and after that function call you go into some wait-mode, and the connection is possibly kept open for hours, days, weeks. Someday, it may throw an exception because the database was shut down, or the database cannot be shutdown because some inactive daemon (yours) keeps open an unused connection. Really, C++ programmers should definitely be scope and RAII aware, and do things as local as sensible. – Sebastian Mach Jun 19 '13 at 15:05
  • @phresnel: That's the reason I wrote _when one is sure that `a` is not used anywhere down the line_. However, I do understand the seriousness of knowing RAII, scope and lifetime of objects (order of stack unwinding) in C++, particularly when one is working on a large project. – legends2k Jun 19 '13 at 15:14
  • I just thought that the formulation might seed some wrong expectations that might turn up as surprises to the asker in some years :) – Sebastian Mach Jun 19 '13 at 15:19
  • @legends2k: I didn't realize that a constructor actually created the object and not just the instantiation itself. But, I guess that makes sense since it is called a "constructor".:) – larrylampco Jun 19 '13 at 18:25
  • Out of curiosity, if vector foo stores a reference to the anonymous object, will the object be reference-able later in the code? I've heard C++ will extend the lifetime of a variable if a reference is kept to it. – Jacob Sharf Nov 24 '13 at 19:12
  • 1
    @JacobSharf: Vectors own the resources contained in them; you [can't create a vector of references](http://stackoverflow.com/q/922360/183120). Extending the lifetime works mostly in case where a object is returned by value and on the caller side it's assigned to a reference due to which the object lives as long as the reference does. I've mostly seen these only at function and local scopes. – legends2k Nov 25 '13 at 06:41
  • 1
    @JacobSharf With C++11's [std::reference_wrapper](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper), one can create a vector of references but it's constructor only takes `T&` and not `const T&` or `T&&` so `foo.push_back(Parameter())` [would not compile](http://coliru.stacked-crooked.com/a/04e181420d5e7969). – legends2k Mar 22 '17 at 05:01
4

That line will create a temporary instance of Parameter and copy it into Foo. Assuming this is pre-C++11 code. The new std::vector<T>::push_back has an overload for rvalues in which case there will be no copies.

David G
  • 94,763
  • 41
  • 167
  • 253
1

when you call Parameter() a temporary object is created and passed to foo.push_back() function. Previously you declared the object with name Parameter a; and passed it to like this foo.push_back(a). By doing like this you can use the object named a down the line of your program.

Priyatham51
  • 1,864
  • 1
  • 16
  • 24
0

You are not passing a constructor, but instead passing a temporary object. When you do Paramater() because of the pharenthesis, it creates a object. Its kind of like a function call for example getInput().

dchhetri
  • 6,926
  • 4
  • 43
  • 56
0

The other point we're missing here is that to pass a function as a parameter you do not use parentheses at all. Here's an example of passing a function as a parameter:

#include <algorithm>
#include <vector>
#include <iostream>

// initialise sum and summing function
int sum = 0;
void sum_numbers( const int& number );

// Create a test for our sum function
int main(int argc, const char * argv[])
{
    // create some numbers
    std::vector<int> numbers;
    numbers.push_back( 34 );
    numbers.push_back( 73 );
    numbers.push_back( 14 );

    // passing "sum_numbers" function as a parameter
    std::for_each( numbers.begin(), numbers.end(), sum_numbers );

    // check that our sum function worked
    std::cout << "The sum of numbers is: " << sum << std::endl;

    return 0;
}

// add the current number to the sum
void sum_numbers( const int& number )
{
    sum += number;
}
Simon Bosley
  • 1,114
  • 3
  • 18
  • 41
0

This subject is old but I'd like to add something, if you truly want to pass a constructor as parameter (as function pointer) without creating a temporary object you can do this hack if you're using a recent enough C++ standard

foo([](){ return MyClass(); });
Fayeure
  • 1,181
  • 9
  • 21