Hacker News new | ask | show | jobs
by mehrdadn 2328 days ago
Could someone please explain why you'd put nodiscard on a constructor? I'm a bit confused as to when that's needed.
3 comments

To avoid this insidious bug:

    std::lock_guard<std::mutex>(m);  // guard is immediately thrown away
versus the correct

    std::lock_guard<std::mutex> g(m);  // hold mutex til end of scope
Note for people who don’t see the difference: if a guard doesn’t have a name, it won’t survive until the end of the scope, thus doesn’t guard anything.
I might be wrong here, but I think that the first one is a declaration of a guard with the name m using the default constructor.

The same way that int (a); and int a; are equivalent.

So the guard should remain until end of scope, but won't guard anything.

Lock guard has no default constructor, so the line will in fact materialize a temporary lock guard around the mutex m, then throw it away at the semi-colon, thus locking nothing.
lock_guard doesn’t have a default ctor, you have to pass a mutex (or presumably invoke a move ctor, but I can’t see one on cppref).
If it's constructed as a temporary rvalue but never stored or passed as an argument, I think there's places where the compiler can elide the code entirely. Whereas you might prefer it have the system side effects associated with construction and destruction.
So it's for copy/move-constructors only?
No. Sorry for being unclear. [1] is a great video that covers a lot of good stuff in particular this usability bug. It's worth watching in its entirety.

If you don't want to sit through the video, here's the broken code in question:

    void Obj::update() noexcept {
        unique_lock<mutex>(m_mutex);
        do_the_mutation();
    }
"unique_lock<mutex>(m_mutex);" has no effect, but you might mistakenly think that this will block on m_mutex. Labeling unique_lock's constructor as [[nodiscard]] would force you to think twice. See [2] for more details.

[1] https://youtu.be/lkgszkPnV8g?t=1767

[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p177...

Ahh, that makes sense! On my phone at the moment but will check out the video too, thanks!
After not using C++ for 15+ years , looking at it now makes my eyes bleed.
Using modern C++ everyday, that’s how I feel looking at C++98 code ;-)
I use it everyday, and I'm still very eager to stop using it due to its growing complexity.

I'm trying to gradually replace C++ with Rust as my primary language, but it's still a lot easier to get a well-paying job in C++ than in Rust.

Rust is both more complex and uglier than modern C++. If your complaint is having to learn new stuff, then Rust isn't the solution.
i’m not disagreeing with you (i’m learning rust, so don’t have a strong opinion yet) but am curious how you feel that way?
That's how I felt looking at C++17 deduction guides, and that's even though I've actually been using C++. If you haven't seen them yet you should check them out ;)