3

I have a function declaration like this:

void foo(std::string const &bar = std::string(""));

Now, we are using MISRA C++, and our code verifier gives an error on the default value's constructor:

RULE 15-5-3: The terminate() function shall not be called implicitly.

I understand that somewhere in the creation of the default parameter there may be a string construction (a sensible compiler would no doubt optimise it out, but MISRA C++'s rules cover stupid compilers too), that is, it is possible to translate:

foo();

To

std::string tmp(std::string("")); // May run out of memory, etc
foo(tmp);

However, is there some way round this, bar the obvious:

void foo(std::string const &bar);
void foo() { foo(std::string("")); }

This might get messy with multiple optional parameters, however...

Ken Y-N
  • 14,644
  • 21
  • 71
  • 114
  • 7
    Have you tried to *default-construct* the string, as in `std::string()`? Since C++17 it's even specified as `noexcept`. – Some programmer dude Aug 20 '19 at 06:17
  • I'll try that out for now - I have to commit everything and wait for our CI system to build, so I won't know what happens until tomorrow. – Ken Y-N Aug 20 '19 at 06:18
  • 3
    C++11 is not allowed in MISRA-C++, nor is C++17. You can't use anything but C++03. Read rule no 1 in the MISRA document. – Lundin Aug 20 '19 at 06:41
  • We have a special dispensation to use C++11 in this project. – Ken Y-N Aug 20 '19 at 06:57
  • I don't think that there is any way that a compiler could optimise out the construction of the default argument in your case - it has to pass *some* string, after all. However, you could use a "prefab" empty string and use that as the default value. – molbdnilo Aug 20 '19 at 07:24
  • 1
    @KenY-N Combining MISRA and C++11 is kind of like placing a sign outside the office saying "Not allowed to blow your leg off", then ensure that the office is filled with land mines... – Lundin Aug 20 '19 at 11:51
  • @Someprogrammerdude OK, that made the error go away, thanks! If you'd like to post that as an answer...? – Ken Y-N Aug 21 '19 at 05:09

1 Answers1

2

Try initialising the default parameter outside of the function declaration:

const std::string def = "";
...
void foo(std::string const &bar = def);
Aykhan Hagverdili
  • 28,141
  • 6
  • 41
  • 93
Paul Evans
  • 27,315
  • 3
  • 37
  • 54
  • Isn't using the constructor more efficient than using `operator=`? `operator=` has to create a temporary and so on. – Aykhan Hagverdili Aug 20 '19 at 07:51
  • @Ayxan On the contrary: With this code, you are using a single object over and over again, always passing it by reference, so you only push a pointer on the stack to pass it. With your code, you are constructing a new object every time `foo()` is called, including the memory allocation overhead. – cmaster - reinstate monica Aug 20 '19 at 08:33
  • @cmaster I think you got me wrong. The global object could have been initialized as `const std::string def{};` instead of `const std::string def = "";` and that would have eliminated a temporary, – Aykhan Hagverdili Aug 20 '19 at 11:25
  • 3
    `const std::string def = "";` is an initialization, not an assignment. You can even have the `operator=()` deleted, and it will still compile without a complaint. And even if it would call `operator=()`, that would be a one-time call, and thus irrelevant for performance. – cmaster - reinstate monica Aug 20 '19 at 12:14
  • @Ayxan The OP is for MISRA C++, so I'm assuming C++03 as latest possible version of C++ being used. So no `{}` initialisation. And both `=` and `()` will call the same copy constructor. – Paul Evans Aug 20 '19 at 12:39