2

My constructor takes an std::array. I'm trying to give it a default value, but calling the constructor without an argument gives this error:

$ g++ -std=c++11 -Wall -Werror -Wextra -pedantic-errors test.cpp Position.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:14:29: error: array must be initialized with a brace-enclosed initializer
  Position *y = new Position();
                             ^
test.cpp:14:29: error: too many initializers for ‘std::array<unsigned char, 8ul>’

Line numbers are different. This is my code:

// test.cpp
int main() {
    Position *x = new Position({1,1,1,1,1,1,1,1}); // works
    Position *y = new Position(); // does not work
}

// Position.cpp
#include <cstdint>
#include <array>
#include "Position.h"
Position::Position( std::array<uint8_t,8> columns_ ) {
    columns = columns_;
}

// Position.h
#ifndef POSITION_H
#define POSITION_H
#include <array>
class Position {
    public:
    Position( std::array<uint8_t,8> = {0,0,0,0,0,0,0,0} );
    private:
    std::array<uint8_t,8> columns;
};
#endif

What have I got wrong?

5
  • 3
    Why don't put an overload Position::Position()? Commented Oct 3, 2013 at 6:35
  • This cannot be done, Passing an array as a parameter with default values into int main() Commented Oct 3, 2013 at 6:37
  • 1
    @cpp he's not trying to do that. He wants a default value for an argument to a constructor, not main. Commented Oct 3, 2013 at 7:19
  • @Adam, I know, I refered to the answer of this question, where it is said, that it is not possible to pass a complete block of memory by value as a parameter to a function, and that it has nothing to do with main(). Commented Oct 3, 2013 at 7:23
  • 1
    @cpp if you were named cpp11 you wouldn't say that. Commented Oct 3, 2013 at 7:49

2 Answers 2

5

You need to repeat the type:

Position( std::array<uint8_t,8> = std::array<uint8_t,8>{0,0,0,0,0,0,0,0} );

while this (or using double-braces) works, it creates a copy on each caller's side when the default is taken. An overloaded constructor would avoid this kind of code-bloat, hence I'd advice to prefer overloads over default parameters.

Sign up to request clarification or add additional context in comments.

4 Comments

these copies are not optimized away by the compiler? since at the call site the compiler knows whether a default argument was supplied or not.
@TemplateRex If the implementation of the method ends up in a different translation unit, the compiler has no chance to optimize it. (maybe, just maybe, LTO can come to the rescue but I would never rely on it)
OK but for STL headers (with their hidden allocators and what not) and other header-only code, this problem does not apply, correct?
@TemplateRex Even then that's not entirely true. Just because the compiler could optimize it away does not mean it actually does. Also, in some cases, the language rules make it extra hard to optimize stuff away. And in the overloads, you might even get away with simplifying the implementation even further. But in general it's always a trade-off between code simplicitly, maintainability, efficiency and code size. The knowledge and awareness of what is really happening is what allows you to make informed decisions - but it's always a decision, I don't believe in one-size-fits-all solutions.
4

double-braces required for the second case to run:

Position( std::array<uint8_t,8> = {{0,0,0,0,0,0,0,0}} );

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.