- I think references should have been const by default - 23 Updates
- A few question about learning c++ - 1 Update
- A few question about learning c++ - 1 Update
| Juha Nieminen <nospam@thanks.invalid>: Oct 21 05:23AM Time and again I see beginner C++ programmers make the same mistake: Make functions take objects by non-const reference, even when (in the vast, vast majority of cases) the function doesn't modify those objects. In one particularly egregious case some beginner programmer had written a comparator lambda that took two std::string objects by reference, wondered why he was getting a compiler error, and then removed the references, so it was taking the objects by value. That way it compiled. Then he wondered why it was so slow. I think it was a mistake to make references non-const by default. It's logical (and consistent with pointer syntax) of course, but I think it was a mistake. In the vast, vast majority of cases if you create a reference to something else, you want it to be const (and there are many good reasons why it should be const). It's extremely rare to explicitly want a non-const reference. And the thing is, C++98 has a *perfect* keyword to explicitly denote that you want a non-const reference, which could have been used for this purpose, so no new keyword would be needed for this: 'mutable'. In other words, I think C++ would have been better if it worked like this: void foo1(std::string& str) { str = "hello"; // error: 'str' is const } void foo2(mutable std::string& str) { str = "hello"; // ok } (You could still write "const std::string&", but it would just have the exact same meaning as "std::string&", ie. in this case the 'const' is superfluous, a bit like how 'signed' is superfluous in "signed int".) |
| David Brown <david.brown@hesbynett.no>: Oct 21 08:54AM +0200 On 21/10/2021 07:23, Juha Nieminen wrote: > the exact same meaning as "std::string&", ie. in this case the > 'const' is superfluous, a bit like how 'signed' is superfluous > in "signed int".) I agree with you entirely. But if we are going for wishful thinking about how C++ could have been made better, I'd have preferred "const" for all variables and required "mutable" to declare a variable that could be modified. (Of course that would mean you'd need something else for class members that are today "mutable". But I think it's a lot more common for people to make variables that could have been "const" but aren't, than to use mutable members.) |
| RacingRabbit@watershipdown.co.uk: Oct 21 09:12AM On Thu, 21 Oct 2021 05:23:03 -0000 (UTC) >the exact same meaning as "std::string&", ie. in this case the >'const' is superfluous, a bit like how 'signed' is superfluous >in "signed int".) Looking for logic in C++ keywords is a hiding to nothing. Eg const_cast actually means remove const'ness , not add it which is frankly bizarre. You might as well have true mean false and false mean true. Similarly putting throw() at the end of a function def means it can't throw! Though at least that insanity has been superceeded by noexcept now. |
| Paavo Helde <myfirstname@osa.pri.ee>: Oct 21 12:18PM +0300 21.10.2021 08:23 Juha Nieminen kirjutas: > I think it was a mistake to make references non-const by default. > It's logical (and consistent with pointer syntax) of course, but I think > it was a mistake. Agreed. By default in C is to pass objects by value, so the changes in the object will not affect the caller side. On the caller side the pass by value and pass by reference look the same, so this important feature (no surprises on the caller side) was lost in C++. Using a const reference fixes this loss, so one can even argue that using a const reference, at least by default would also be logical and consistent, in some sense. If it were up to me, I would have required extra syntax on the caller side to pass via non-const reference, like @var. Pushing everything more const would mean the language would behave and feel more "functional" and less "OOP", but that's a good thing. |
| Juha Nieminen <nospam@thanks.invalid>: Oct 21 09:48AM > for class members that are today "mutable". But I think it's a lot more > common for people to make variables that could have been "const" but > aren't, than to use mutable members.) That would quite quickly turn quite annoying, eg. with things like for-loops: for(int i = 0; i < 10; ++i) // error, i is const |
| Juha Nieminen <nospam@thanks.invalid>: Oct 21 09:52AM > Looking for logic in C++ keywords is a hiding to nothing. Eg const_cast > actually means remove const'ness , not add it which is frankly bizarre. What would have been a better name for that keyword in your opinion? > Similarly > putting throw() at the end of a function def means it can't throw! Though at > least that insanity has been superceeded by noexcept now. I think it's pretty logical. It just lists all the exceptions that the function can throw. If the list is empty, it means it doesn't throw any exception. If they wanted to be clearer, it should have been "throws(whatever)", but that would have required adding yet another single-use keyword. |
| Paavo Helde <myfirstname@osa.pri.ee>: Oct 21 12:55PM +0300 21.10.2021 12:48 Juha Nieminen kirjutas: > That would quite quickly turn quite annoying, eg. with things like > for-loops: > for(int i = 0; i < 10; ++i) // error, i is const Solved by C++20: for (int i : std::ranges::iota(0, 10)) Having const default would mean additional bonus in that 'i' would be const inside the loop body. |
| RacingRabbit@watershipdown.co.uk: Oct 21 10:36AM On Thu, 21 Oct 2021 09:52:53 -0000 (UTC) >> Looking for logic in C++ keywords is a hiding to nothing. Eg const_cast >> actually means remove const'ness , not add it which is frankly bizarre. >What would have been a better name for that keyword in your opinion? unconst_cast , noconst_cast, take your pick. >I think it's pretty logical. It just lists all the exceptions that the >function can throw. If the list is empty, it means it doesn't throw >any exception. Except throw inside a function means throw any exception currently on the stack. You can't have it both ways and for once the C++ committee saw sense and replaced it with noexcept. >If they wanted to be clearer, it should have been "throws(whatever)", but >that would have required adding yet another single-use keyword. There's nothing wrong with single use keywords if they make things clearer. This should have been done with the = 0 in pure virtuals and the spurious int in postfix operator definitions. eg: virtual void myfunc() = 0; -> pure virtual void myfunc(); myclass &operator++(int) -> myclass &operator++() postfix |
| David Brown <david.brown@hesbynett.no>: Oct 21 12:57PM +0200 On 21/10/2021 11:48, Juha Nieminen wrote: > That would quite quickly turn quite annoying, eg. with things like > for-loops: > for(int i = 0; i < 10; ++i) // error, i is const for (mutable int i = 0; i < 10; ++i) Yes, there are many places where you want variable variables - but I think overall you typically have more that could be declared const than have to be variable. (The idea is not without precedence - there are other modern languages with constant objects by default.) For loops, I think the best solution would be a mixture - the loop variable should be mutable within the controlling expressions, but should be constant within the statement or block - as though you had written: for (int i = 0; i < 10; i++) { const auto i_ = i; const auto i = i_; // Here, "i" is constant } |
| Bonita Montero <Bonita.Montero@gmail.com>: Oct 21 01:13PM +0200 You're compulsive. |
| "Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Oct 21 01:22PM +0200 On 21 Oct 2021 07:23, Juha Nieminen wrote: > reference to something else, you want it to be const (and there are > many good reasons why it should be const). It's extremely rare to > explicitly want a non-const reference. Agreed. So what can you do about it? Just define template< class T > using Ref_ = const T&; And then write void foo( Ref_<Baluba> x ) instead of void foo( const Baluba& x ) A more clever definition in terms of a nested type of a class template, like the standard library usually does, does not support type deduction for function templates, but the above supports e.g. template< class T > void foo( Ref_<T> x ) with calls like `foo( something )`. When the same approach is adopted for pointers it supports general left/west `const`. The one big drawback of this approach is that code using such definitions can't be posted to this group without Mr. Fibble complaining loudly and posting offensive remarks about how it's impossible to grok. > the exact same meaning as "std::string&", ie. in this case the > 'const' is superfluous, a bit like how 'signed' is superfluous > in "signed int".) - Alf |
| Manfred <noname@add.invalid>: Oct 21 01:57PM +0200 On 10/21/2021 7:23 AM, Juha Nieminen wrote: > the exact same meaning as "std::string&", ie. in this case the > 'const' is superfluous, a bit like how 'signed' is superfluous > in "signed int".) Good point. However, I value syntax consistency a lot, so given the current state of things (non-const default pointers) I think non-const default references are preferable to me - and I write /many/ more 'const T&' declarations than 'T&' myself. In an ideal world, if we were able to have const default pointers as well, then I would endorse your view entirely. BTW Alf's alternative has its appeal. |
| Bo Persson <bo@bo-persson.se>: Oct 21 03:08PM +0200 On 2021-10-21 at 13:13, Bonita Montero wrote: > You're compulsive. Who, me? |
| RacingRabbit@watershipdown.co.uk: Oct 21 01:40PM On Thu, 21 Oct 2021 12:57:05 +0200 >variable should be mutable within the controlling expressions, but >should be constant within the statement or block - as though you had >written: I think const is a lot of fuss about nothing frankly. I barely use them anyway and I can't remember the last time that I had a bug due to updating a variable that shouldn't have been updated. For those who think its simply an indication to other devs that a variable won't be changed then fair enough but personally I find a lot of const/non const compilation errors related to functions a PITA. |
| Bart <bc@freeuk.com>: Oct 21 03:04PM +0100 > an indication to other devs that a variable won't be changed then fair enough > but personally I find a lot of const/non const compilation errors related > to functions a PITA. I don't about C++, but in C, you can take a program, remove all the 'const' qualifiers, and it will still compile and work. Makes you think... |
| Manfred <noname@add.invalid>: Oct 21 04:41PM +0200 On 10/21/2021 4:04 PM, Bart wrote: > I don't about C++, but in C, you can take a program, remove all the > 'const' qualifiers, and it will still compile and work. > Makes you think... ...mumble, obviously 'const' is almost exclusively for the programmer's convenience (some implementations may use it to map some const data to read only memory, but that's probably a minor use compared to the massive benefit in accurate modeling of a process). The categories of immutable and mutable data are pretty relevant in process modeling, and since SW design is a lot about modeling, long live 'const'. |
| RacingRabbit@watershipdown.co.uk: Oct 21 02:51PM On Thu, 21 Oct 2021 15:04:19 +0100 >I don't about C++, but in C, you can take a program, remove all the >'const' qualifiers, and it will still compile and work. >Makes you think... Well quite. But then I started out in C and const wasn't a thing so you had to know what was going on and not always rely on the compiler to tell you. But then C doesn't have references I suppose and its a bit difficult to accidentaly dereference a pointer and update it unlike a C++ reference. Even so, I still don't like consts. But its just personal taste. |
| RacingRabbit@watershipdown.co.uk: Oct 21 02:57PM On Thu, 21 Oct 2021 16:41:34 +0200 >The categories of immutable and mutable data are pretty relevant in >process modeling, and since SW design is a lot about modeling, long live >'const'. Tbh if you don't know which data should be left alone and which you can update you probably shouldn't be working on the code until you learn it a bit better. As for private/protected variables in library classes, that just pisses me off. If I want to alter something then let me Mr Library Coder. Its not up to you to decide what I can and can't alter in my own program and you're not going to be able to think up every possible use case in which your "private" variable might need to be accessed or changed. I actually had this issue with an in house lib at a company but the muppet who wrote it refused to make the variable public or even available via a setter even though we needed to access it. In the end I got the address of a public variable in the class, counted back in memory and dereferenced the pointer where his private var was stored. Worked a treat though very fragile. Eventually management made him add a getter function so that hack was removed. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 21 12:07PM -0400 On 10/21/21 5:12 AM, RacingRabbit@watershipdown.co.uk wrote: ... > Looking for logic in C++ keywords is a hiding to nothing. Eg const_cast > actually means remove const'ness , not add it which is frankly bizarre. You can use const_cast<> to add const as easily as removing it. Doing so is normally unnecessary, because such conversions can be done implicitly, which might be what gave you that impression. You can also add and remove the other qualifier, volatile. Therefore, I think qual_cast<> might have been a better name for it. |
| James Kuyper <jameskuyper@alumni.caltech.edu>: Oct 21 12:09PM -0400 On Thu, 21 Oct 2021 15:04:19 +0100 Bart <bc@freeuk.com> wrote: ... >I don't about C++, but in C, you can take a program, remove all the >'const' qualifiers, and it will still compile and work. >Makes you think... Keep in mind that this is strictly true in C only if you remove all the "const" qualifiers from all of the #included header files, and you can't do that with standard library headers. It would also be difficult to do with the headers associated with third-party libraries. More importantly, that's true only if the program would compile without diagnostics before the removal of the 'const' qualifiers, and there's a simple, blindingly obvious reason for that, which does NOT count as an argument against the proper use of "const": The declaration of an identifier containing the 'const' keyword indicates that this identifier should not be used in any way that puts the object qualified by that keyword in danger of being modified. The purpose of that keyword is to enable diagnostic messages when the identifier is used in an expression that could put that object in danger of being modified. If your program generates no diagnostics, that means that it contains no such expressions. Removing "const" from the entire translation unit, including #included headers, will not change the fact that there is no danger, and the program should therefore work just the same as before. However, if you modify the program again after removing all "const" keywords, that modification might create such a danger, but the implementation no longer has any obligation of warning you about the danger. You said that you don't know about C++. Well there's an important difference between C++ and C in this regard: function overloading. A function can be overloaded based upon the difference in the way one or more of its arguments is qualified. The overloads may do significantly different things - if so, the non-const overload usually attempts to modify the relevant object, whereas the const overload uses some work-around to avoid the need to modify it. That work-around is usually inconvenient in some way, otherwise there would have been no need to declare the const overload. Therefore, at best, removing all use of the "const" keyword would require that the non-const overload be dropped, and that the less convenient const overload be used at all times. That's "usually". Overloads are entirely under the programmer's control, and the difference between them need not be "usual" - it very often isn't. It would be trivial to create overloads that do significantly different things with const and non-const arguments (most trivially, they could print out "const" and "non-const" respectively). No single function can replace both overloads, but it would have to do so if you removed all occurances of the "const" keyword. |
| Branimir Maksimovic <branimir.maksimovic@icloud.com>: Oct 21 09:27PM > the exact same meaning as "std::string&", ie. in this case the > 'const' is superfluous, a bit like how 'signed' is superfluous > in "signed int".) Good thinking, but now to late, perhaps with -std=c++22 and latter on? -- 7-77-777 Evil Sinner! with software, you repeat same experiment, expecting different results... |
| Bart <bc@freeuk.com>: Oct 21 11:49PM +0100 On 21/10/2021 17:09, James Kuyper wrote: > declare the const overload. Therefore, at best, removing all use of the > "const" keyword would require that the non-const overload be dropped, > and that the less convenient const overload be used at all times. Actually here's an example from C where const changes the behaviour: #include <stdio.h> #include <stdint.h> int main(void) { #define issigned(x) _Generic((x),\ int8_t: "S",\ int16_t: "S",\ int32_t: "S",\ const int32_t: "const S",\ int64_t: "S",\ uint8_t: "u",\ uint16_t: "u",\ uint32_t: "u",\ uint64_t: "u",\ default: "other") int32_t x; // const int32_t x; puts(issigned(x)); } The output is different when x has a const attribute. |
| "james...@alumni.caltech.edu" <jameskuyper@alumni.caltech.edu>: Oct 21 04:21PM -0700 On Thursday, October 21, 2021 at 6:49:29 PM UTC-4, Bart wrote: > > "const" qualifiers from all of the #included header files, and you can't > > do that with standard library headers. It would also be difficult to do > > with the headers associated with third-party libraries. ... > puts(issigned(x)); > } > The output is different when x has a const attribute. You're correct, I forgot about that. _Generic provides a capability similar to but much more restricted than function overloading, and as such allows the behavior to depend upon the qualifiers. |
| Manfred <noname@add.invalid>: Oct 21 04:55PM +0200 On 10/21/2021 3:07 PM, rabbit rabbit wrote: > -The latest book I have read is 《C++ primer》,but it only talks about some features of C++11. I would like to know if there are any good books or videos that can help me learn the latest C++ features. > * Do I need to change my reading books? > - The three books I am currently reading are 《Effective c++》,《More Effective C++》and 《The Annotated STL Sources》,After reading for a while, I found that these three books are too old, some of the C++ features mentioned in them are out of date, should I continue reading or find some new books. If I should find new books, then do you have any recommendations for books? That is one decent list: https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list |
| rabbit rabbit <1604456428@qq.com>: Oct 21 06:07AM -0700 I know this place from the book 《More Effective C++》.I heard from that book that there are many c++ experts here and I would like to ask for help on the following questions .Sincere thanks everyone .* is followed by the name of the question and - is followed by some details * Where is the best c++ forum in the world right now - The two places(comp.lang.c++.moderated,comp.std.c++) mentioned in that book have been unattended for a long time, and the most recent reply is in 2016. emmmmmm, I know my information is a bit outdated,so that is reason why i am asking this foolish question. Is it right here or on StackOverflow or somewhere else? * Where can I learn about the latest features of C++14/17/20? -The latest book I have read is 《C++ primer》,but it only talks about some features of C++11. I would like to know if there are any good books or videos that can help me learn the latest C++ features. * Do I need to change my reading books? - The three books I am currently reading are 《Effective c++》,《More Effective C++》and 《The Annotated STL Sources》,After reading for a while, I found that these three books are too old, some of the C++ features mentioned in them are out of date, should I continue reading or find some new books. If I should find new books, then do you have any recommendations for books? |
| You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment