I think a good follow-up to const member functions is a talk about the 'mutable' keyword, some quite naughty things can be done with that, possibly entering the area of "undefined behaviour"? Not sure though.
@LemonChieff
2 жыл бұрын
I thought that was the `volatile` keyword 🤔
@zamf
2 жыл бұрын
@@LemonChieff No, volatile is a different story. That's why Jason should cover this in more detail. 'volatile' means "the value of this variable may change at any point so the compiler is not allowed to assume anything about it", while 'mutable' means "please, compiler, let me modify this variable even when 'this' is const". The first one changes how the compiler and the optimizer treats the variable, while the second one is just a way to suppress the compiler error and say "I know what I'm doing".
@ajinkyakamat7053
2 жыл бұрын
@@zamf you are confusing const_cast with mutable. Modifying a member variable marked as mutable in a const function is not UB, but infact the intended use case for mutable. An example of where such a feature would be used is caching. Imagine you have a class that reads a file and stores it internally in memory. This class has a member function computeHash(). In this case, the computeHash() is supposed to be const coz you are computing the hash and returning it without modifying the file. But if the file is too long then you might want to compute the hash and cache it so you get a perf boost for the computeHash() call. In this case, you create a hash member variable mark it as mutable and calculate it in computeHash() function.
@zamf
2 жыл бұрын
@@ajinkyakamat7053 That was my point. I didn't claim that using 'mutable' leads to UB. That's why I think that Jason should cover this in more detail to remove any confusion.
@ajinkyakamat7053
2 жыл бұрын
@@zamf Ah. Yes. You didn't. The original commenter did. Sorry my bad. But, in the last paragraph, the behavior you describe is that of const_cast not mutable. Mutating a mutable member is not an error.
@thestarinthesky_
11 ай бұрын
@10:25 It captures the essence of what's happening: in C++, const-ness is indeed shallow and doesn't propagate through to objects pointed to by member pointers, unless those pointers are themselves pointers-to-const. Great example! every time I watch the same video, I learn something new. Thanks.
@gtyron
2 жыл бұрын
I think L Value and R Value functions would be a good topic as well. I just recently learned they are a thing, and I'm not entirely sure I'm using the right terms.
@etiennelemieux472
2 жыл бұрын
"What Are `const` Member Functions?" Easy, they are what I miss the most in C#
@thestarinthesky_
11 ай бұрын
Great content! Thank you so much for making the content understandable and so clear for intermediate and beginner learners. ❤
@alexskatkov2124
2 жыл бұрын
Returning char* from begin() const is well formed, while we did not implement it. In definition we will write something like that: return buffer; where buffer is an array of type char*. And here we meet a problem, because this-> buffer is expression with type const char*& , because (this) is expression of type const string* in const methods, what is important point too. Love your videos.
@cppweekly
2 жыл бұрын
Yeah, I intentionally at that moment avoided going down that road.
@Phroggster
2 жыл бұрын
Really wish you would've lightly touched upon the common cbegin() and cend() iterators, if only to show how they can prevent accidental modifications.
@cppweekly
2 жыл бұрын
You just gave me an idea for a different episode that will cover this more directly
@ric.larsson
2 жыл бұрын
I think you miss a very important overload in your introduction: rvalue. These are kind of neat to use.
@RaaynML
2 жыл бұрын
Can confirm, super useful
@michaelmahn4373
2 жыл бұрын
Really? I know what they are, but I've never found a practical use-case for them.
@Dziaji
2 жыл бұрын
No. Const member functions have nothing to do with rvalues. If he was talking about const reference parameters, then rvalues would be relevant.
@ultradude5410
2 жыл бұрын
@@Dziaji maybe talking about ref-qualified member functions? struct S { int val() & { return 5; } int val() && { return 10; } }; int main() { S example; assert(example.val() == 5); assert(S().val() == 10); } I’m not sure when these would be useful, but there ya go.
@Dziaji
2 жыл бұрын
@@ultradude5410 Holy crap! Thank you! I had no idea ref qualifying a member function was something that could be done. I don't really have a use for it at the moment, but I make a lot of complex template classes and I'm sure it will come in handy. C++ is so complex that after all these years, I still come across new things. As cool as this is though, I don't think that is what Richard was talking about.
@kfitch42
2 жыл бұрын
const member functions cannot modify "this", but can modify any other global objects. I wish there was some some way to mark a function/method as "const" with respect to globals. This is something that FORTRAN can do with "pure" functions. This allows the compiler to optimize in some very interesting ways, e.g. common subexpression elimination (CSE) on function calls without inlining. Also, it might be interesting to discuss aliasing rules as a follow up to this. E.g. what if we pass a (non-const) pointer/reference to "this" to a const method.
@Dziaji
2 жыл бұрын
There is no reason you can’t take a const reference to the global in your function.
@cppweekly
2 жыл бұрын
See also: kzitem.info/news/bejne/mZCurXV4gZWmZ2U
@KennyMinigun
2 жыл бұрын
3:47 worth noting also, that not all systems allow you to return the whole 32 bit value. The return value is likely be truncated when outside the allowed range.
@zamf
2 жыл бұрын
I think you should also mention about how to allow modifying private member variables in const member functions, for example for caching.
@cppweekly
2 жыл бұрын
This is somewhere between difficult to impossible to really do well, and do correctly, particularly if you take into account thread safety. I've completely eliminated the use of `mutable` in my code because of this. (Specifically, `const` member functions should be safe for multithreaded reads, as specified in the C++ standard. This is one reason why GCC had to remove COW functionality from their std::string implementation)
@zamf
2 жыл бұрын
@@cppweekly You're right. I didn't consider multithreading and I see the problems 'mutable' can cause. Maybe you can lock the cached object and the dirty bit while updating them but locking has its own problems, so, yeah, it's more complicated than I thought.
@nidefawl2552
2 жыл бұрын
In a perfect world the size member function would automatically be declared const. And noexcept. And [[nodiscard]]. Why do I even have to write getters myself?!
@treyquattro
2 жыл бұрын
you believe you've covered this in a nutshell? O'Really?
@PaulMetalhero
2 жыл бұрын
does gcc support format yet?
@therealchonk
2 жыл бұрын
AFAIK unfortunately not yet (as of GCC 12)
@camerashysd7165
7 ай бұрын
sponsored by me😂
@pandacongolais
Жыл бұрын
You should teach ;-)
@slipcurve1410
2 жыл бұрын
with class i never write private. i just declare the privates first and then do a public access modifier at the end. it's weird to flip the class default backwards. i know a lot of people have that habit, but i no clue as to why.
@zamf
2 жыл бұрын
I think the point is that the variables in a class are an implementation detail and should not be the first thing you see in a class definition. The first thing should be the public interface of the class because that's what you care about when using that class.
@slipcurve1410
2 жыл бұрын
@@zamf I guess, although I don't agree. When I want to see what a class provides, I use code completion tools that expose it, without opening the header. If I open the header, I explicitly want to see the internals. So it's a poor excuse to flip the natural default of class.
@Dziaji
2 жыл бұрын
Some people like to make all the member functions first and then all the member variables after. If you have a mix of public and private functions and variables, you can’t avoid using the word private or public and keep the functions all before the variables.
@zamf
2 жыл бұрын
@@slipcurve1410 I guess it's for historical reasons. Some programmers don't use a specialized IDE to write code. Some use text editors like Vim or Emacs and in those cases you have to open the header file to see what functionality is available. I agree in modern IDEs the structure of the class doesn't matter that much because you can use code completion and hits from the editor.
@X_Baron
2 жыл бұрын
The keywords class and struct also change the default base class access (private and public, respectively). When programming in a traditional (?) object-oriented style, public inheritance seems more natural and there's normally no use for private inheritance. Hence struct can be an obvious choice. Also, if a class consists of just variables and getters and setters, you may opt to just expose everything and write a struct to have clean code.
@negidrums915
2 жыл бұрын
“So there is no fundamentally changed concepts here in any recent versions of c++” except for ranges
@Dziaji
2 жыл бұрын
Ranges don’t change how const member functions work.
@negidrums915
2 жыл бұрын
@@Dziaji That' right. However, ranges violate how to propagate constness correctly. std::vector v(42); const auto rng = v | std::views::drop(2); *rng.begin() = 42; // not error even though rng is const
@Dziaji
2 жыл бұрын
@@negidrums915 There are actually 2 schools of thought. In my way of thinking, constness is correct in your example. If you had "std::vector v(42);" and you were still able to set "rng.begin() = 42;", then that would be a violation of constness. In 1 school of thought, the constness of the container should flow to the elements themselves, and in the other, the constness of the elements is separate from the constness of the containers. I adhere to the latter, so this is perfectly fine in my way of thinking: const vector v(20); v[0] = 42; but this would not be correct: v.resize(40); and this would also not be correct: const vector v(20); v[0] = 42;
@cppweekly
2 жыл бұрын
I don't like this, but it is consistent with shared_ptr, for example
@negidrums915
2 жыл бұрын
@@cppweekly Pointer-like types have 2 versions of constness as Dziaji pointed out. const shared_ptr works like int* const, not const int*. Similarly, const vector::iterator corresponds to int* const and vector::const_iterator corresponds to const int*. But ranges are not pointer-like and it looks weird for me.
@homomorphic
2 жыл бұрын
Gcc is so broken.
@Dziaji
2 жыл бұрын
No it’s not. It’s amazing.
@gassarro
2 жыл бұрын
this is pointless. you said 'new to c++', yet you used size_t. trust me, whoever is new to c++ would have used int. i doubt there are many who learned about std components before learning about const member functions. and [[maybe_unused]] if you new to c++, really? i usually like your videos, but this one is definitely a miss. if i didnt know what const member functions are, i would be even more confused by your explanations.
@ChrisOffner
2 жыл бұрын
I’m new to C++ and I disagree. Even from my minimal previous experience in C I’m familiar with *size_t,* and I didn’t have to know *[[maybe_unused]]* ahead of time to understand that it was merely used to shut up the compiler for the purpose of explanation.
@gassarro
2 жыл бұрын
@@ChrisOffner what is 'new to c++' means then? from my perspective it is someone who is like several days in, trying to sort an array and only getting to classes. my point is, if i stumbled upon this video trying to figure out what const member functions are, i wouldnt get it here. is size_t, fmt, [[maybe_unused]] really essential for this? or is it too overwhelming for the newcomer to digest in one go?
@ChrisOffner
2 жыл бұрын
@@gassarro In my case, “new to C++” means that I have the most basic C knowledge you’d get from an “Intro to CS” course, am familiar with OOP (from Java) but have been learning C++ for less than a week now. I appreciate your concern for newcomers, and I agree that [[maybe_unused]] could have been avoided, but neither it nor size_t bothered me, and I actually appreciate the use of fmt if it’s the recommended thing to use in modern C++ (over std::cout). One of my bigger frustrations with learning C++ is that of the 40 years of tutorials that have accrued, barely any of them seem to bother with keeping up with the newest best practices and modern language features, and so it’s insanely difficult to learn what a consistent, safe, efficient, and idiomatic C++ codebase started in 2022 should look like.
Пікірлер: 57