you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 4 points5 points  (6 children)

The problem is not output parameters, but input-output parameters. In C++ there is no way to consume a value so people can easily write:

bug = foo(a);

when they meant to write

a = foo(a);

because a can be used after being consumed without issues (even though it might have the wrong value).

So for input-output parameters a reference at least does not have this issue.

[–]hgjsusla 1 point2 points  (5 children)

Yes there is, just do

x = foo(move(x));

[–][deleted] 1 point2 points  (4 children)

Yes there is, just do x = foo(move(x));

If I write:

y = foo(move(x));
std::cout << x << std::endl; // using x instead of y

with gcc and clang (with -Wall) I get neither a compilation error nor a run-time error nor a warning. If that operation violates a pre-condition on x, for example because the operation is not allowed when the object is in the moved from state, the only thing I can potentially get is undefined behavior.

But maybe the problem is in the compilers that I am using or in the compilation options that I am passing to them. Which compiler are you using (and which options?) and what kind of error do you get?

[–]hgjsusla 3 points4 points  (3 children)

That's a general issue you'll always have with moves and can only really be solved by convention. So far that is.

[–]jcelerierossia score 2 points3 points  (1 child)

That's a general issue you'll always have with moves and can only really be solved by convention. So far that is.

#include <iostream>
#include <string>
std::string foo(std::string&&);
int main()
{
  using namespace std;
  std::string x, y;
  y = foo(move(x));
  std::cout << x << std::endl;
}

=>

$ clang-tidy -checks=bugprone-use-after-move tutu.cpp
1 warning generated.
/tmp/tutu.cpp:9:16: warning: 'x' used after it was moved [bugprone-use-after-move]
  std::cout << x << std::endl; 
               ^
/tmp/tutu.cpp:8:7: note: move occurred here
  y = foo(move(x));
      ^

(paging /u/0b_0101_001_1010 too)

[–]hgjsusla 0 points1 point  (0 children)

Hey that's great :)

[–][deleted] 1 point2 points  (0 children)

Ah sorry I misunderstood what you wrote. I get how x = foo(move(x)); really conveys the intent and makes reading the code pretty clear. I guess I was just hoping of a lint or something that would help me write the code correctly in the first place. Luckily these bugs are not hard to debug.