Menu

std::move to function parameter

2023-03-23
2023-05-01
  • Daniel Marjamäki

    I wonder if it's unsafe to use std::move in a function call if the destination function parameter is a reference?

    Example code:

    class C {
    public:
        C() { std::cout << "C\n"; addr(); }
        void addr() const { std::cout << (void*)this << "\n";
        }
    };
    
    void foo(const C& c) {
        std::cout << "foo\n";
        c.addr();
    }
    
    int main() {
        C c;
        std::cout << "call foo\n";
        foo(std::move(c));  // <- Is this unsafe?
        return 0;
    }
    

    In the output we can see that the constructor for C is only called once.
    The `C::addr() prints the same output both times.

    Does it mean that the c parameter that foo gets is a reference to a moved object and any use of that would be UB? If this is true it feels like Cppcheck could warn when std::move is used in a function call and the parameter is a reference?

     

    Last edit: Daniel Marjamäki 2023-03-23
  • Daniel Marjamäki

    The real code I saw that made me wonder does not use std::move directly. There is usage of std::accumulate and 4th argument is a lambda that takes first parameter by-reference.

     std::accumulate(a.begin(), a.end(), std::string(),
                     [&](std::string&, int) {...});
    
     

    Last edit: Daniel Marjamäki 2023-03-23
  • Jens Yllman

    Jens Yllman - 2023-03-23

    cppreference state, "std::move is used to indicate that an object t may be "moved from", i.e. allowing the efficient transfer of resources from t to another object.

    In particular, std::move produces an xvalue expression that identifies its argument t. It is exactly equivalent to a static_cast to an rvalue reference type. "

    Which kind of say it is never a move, only a conversion of type, which may result in a move. But in this case it will only be a reference to the value. Or am I wrong? Looking at this code both in Compiler Explorer and CppInsight does not show any call to move constructor or move assignment. And adding those function only to print text only result in no code.

    I was little bit expecting it to be different in C++11/14 then in C++17 and later. Since the total concept of all this r/l/pr/x/gl-value was changed in C++17(xvalues).

    But anyway, my feeling of std::move()/std::forward() is little bit unsafe, and if there are some cases that are not good, cppcheck should show a warning.

     
  • CHR

    CHR - 2023-03-23

    The code has no UB, and no move takes place, as noted above.
    clang-tidy evens warns about that: https://godbolt.org/z/5Wdhn8q4b
    Besides that, classC doesn't have any members that could be moved. Also, a moved-from object is supposed to be in a valid but unspecified state.

     
    • Daniel Marjamäki

      Thanks!

       
  • Fraser

    Fraser - 2023-05-01

    Returning a local object with std::move prevents the preferable use of RVO or NRVO. That is worth having a warning for. Another one thats related is that deleted functions should be public to obtain messages related to the deleted status rather than accessibility.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.