48

I have a function,

void test( vector<int>& vec );

How can I set the default argument for vec ? I have tried

void test( vector<int>& vec = vector<int>() );

But there's a warning "nonstandard extension used : 'default argument' : conversion from 'std::vector<_Ty>' to 'std::vector<_Ty> &'"

Is there a better way to do this ? Instead of

void test() {
    vector<int> dummy;
    test( dummy );
}

Regards, Voteforpedro

voteforpedro
  • 483
  • 1
  • 4
  • 4

6 Answers6

75

Have you tried:

void test(const vector<int>& vec = vector<int>());

C++ does not allow temporaries to be bound to non-const references.

If you really to need to have a vector<int>& (not a const one), you can declare a static instance and use it as a default (thus non-temporary) value.

static vector<int> DEFAULT_VECTOR;

void test(vector<int>& vec = DEFAULT_VECTOR);

But beware, because DEFAULT_VECTOR will (can) be modified and won't reset on each call ! Not sure that this is what you really want.


Thanks to stinky472, here is a thread-safe alternative:

Instead of providing a default value, you might as well overload test() with a zero-parameter version which calls the other version:

void test()
{
  vector<int> vec;
  test(vec);
}
Community
  • 1
  • 1
ereOn
  • 53,676
  • 39
  • 161
  • 238
  • 8
    +1 but I think it should be pointed out that 'test' would generally not be thread-safe were it to modify this 'DEFAULT_VECTOR'. It might be tedious, but I'd strongly recommend writing two functions for such needs (one can reuse the other): void test() {vector temp; test(temp); } – stinky472 Jun 30 '10 at 08:45
  • 1
    As a side note, there is a hacky way of getting a reference to a temporary if you can use some method on the latter that returns such a reference to itself... e.g. `operator=`. So, `void test(vector& vec = vector().operator=(vector()));` should work (the lifetime of the temporary is unaffected here and will remain sufficient to handle the call). But please don't do it :) – Pavel Minaev Jun 30 '10 at 14:59
  • Thanks for the answer. But I don't understand why the DEFAULT_VECTOR should be static. Can you please explain? – badri18 May 04 '20 at 21:13
8

I find it questionable for a non-const reference argument to have a default value. What is this supposed to mean?

Commonly, a function taking a non-const reference means "I might change the argument". If the argument is optional why no pass a (non-const) pointer? That way, when callers don't want to pass an arguments, they can pass NULL.
(See here for more information on how to pass function arguments.)

Edit: Well, and of course, there's also overloading. Just add another overload which doesn't take this argument.

Community
  • 1
  • 1
sbi
  • 219,715
  • 46
  • 258
  • 445
7

You could just make pass a pointer to a vector and initialize it to NULL

void test( vector<int>* vec = NULL );
Ahmed Hamdy
  • 71
  • 1
  • 1
5

I know this question was asked in 2010 but for C++11 you can do it like this:

void test( vector<int>& vec = {}) {
      // Awesome code here
}

As pointed out in this answer.

JohnJohn
  • 325
  • 1
  • 6
  • 17
  • 5
    This has the same meaning as `void test( vector& vec = vector() );` as in the question, which is illegal due to attempting to bind a temporary to a non-const reference. In the answer you link to, it is not a reference. – M.M Aug 20 '17 at 05:21
4

We cannot initialize mutable references to temporaries. Only const references allow this. What you are after is most likely this:

void test( const vector<int>& vec = vector<int>() );

Aside from avoiding undefined behavior, this makes the most sense logically and from a const-correctness perspective. If you wanted 'test' to modify the original vector being passed to it, you would not have been able to sensibly provide a default value. Thus it's obvious you are using 'vec' here for read-only purposes and should therefore make it a const reference.

stinky472
  • 6,737
  • 28
  • 27
  • 2
    You cannot initialize mutable references to temporaries directly, period. A temporary won't bind to a reference-to-non-const - if you try that, it's not U.B., it's ill-formed input (i.e. compiler error). VC++ lets you do this, but rightly notes that it is a language extension. – Pavel Minaev Jun 30 '10 at 07:52
  • @Pavel ah good point! I've seen nasty compilers that allowed this behavior like MSVC and past versions of CodeWarrior where the code built but crashed. I will modify the post accordingly for accuracy. Thanks for pointing it out. – stinky472 Jun 30 '10 at 08:00
0

I know this question was asked almost 10 years ago. But for anyone finding its solution now, I've got exactly that for you. I basically have three different methods:

void test(vector<int>vec = vector<int>(10, 0){//definition}

This can be used if it has to be if the default vector has a given size with a common initialiser value.

void test(vector<int>vec = vector<int>{1, 2, 3, 4}){//definition}

This can be used if it has to be if the default vector has a given size with a different initialiser values.

A different approach could be to define a global vector object as:

vector<int> globalvector;

(initialised or uninitialised) and the passing this object as default value as

void test(vector<int>vec = globalvector){//definition}

An important benefit of the last one is that it gives more control over the default value itself as functions can be used to assign values to this globalvector before control reaches the test() function. Another benefit is that (as far I've yet found), if the function involves passing by reference, this works just as fine as:

void test(vector<int>& vec = globalvector){//definition}

unlike the former two.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83