I've recently come back to Chili's tutorials after a long while and as I'm learning I keep wondering about some aspects of C++ that seem peculiar to me.
So, in no particular order:
1.) Is there a consistent naming convention in the standard library? Is it defined somewhere?
2.) Why do names have to be fully qualified? I know you can use "using namespace std;" but it's discouraged. What I'm trying to understand here is, from a technical standpoint, why can you litter your source files in C# with using statements without issue, but it causes problems in C++? Couldn't C++ just force you to fully qualify ambiguities as in C#?
3.) A lot of the names of functions or member variables seem unintuitive. Perhaps this is due to my unfamiliarity with the language, but to provide one specific example: vector.push_back, why push_back? Why not add?
4.) Some of the standard library classes lack functionality that I would expect. For example, std::string contains no tolower/toupper functions, another example, vector has no contains function. I know some of this functionality is in algorithm, but why wouldn't it be part of the class?
Anyway, I'm trying to better understand the design philosophy of C++ and some things just look really weird to me from my C# background. I'm really enjoying the series. Chili is a very engaging teacher.
Random C++ questions from a C# programmer
-
- Posts: 16
- Joined: October 30th, 2017, 11:50 pm
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: Random C++ questions from a C# programmer
The only naming convention that I know of is all types, functions are lowercase to try and avoid collision with other programmers' code. Names beginning with _ are for standard library implementers and names beginning with __ are reserved for compiler implementations. Using this same naming scheme is considered undefined behavior.1.) Is there a consistent naming convention in the standard library? Is it defined somewhere?
The 'using namespace std' is really only discouraged in header files because of possible naming collisions. Because source files ( .cpp files ) are or should never be #include'd it can be done in these files, though it's possible a name collision can still happen. This is the whole purpose of a namespace, to have types with the same name and avoid naming collisions. As for functions, they can be overloaded, but because of the way the compiler mangles the names of functions to avoid naming collisions or calling the wrong function they cannot have the same signature. void foo(int) and void foo(int) are the same signature even if declared in two different header files. So you must put one or both in a namespace to distinguish between the two.2.) Why do names have to be fully qualified? I know you can use "using namespace std;" but it's discouraged. What I'm trying to understand here is, from a technical standpoint, why can you litter your source files in C# with using statements without issue, but it causes problems in C++? Couldn't C++ just force you to fully qualify ambiguities as in C#?
The intent of push_back() in particular is to push a new item to the back of the vector. While add() to you may seem like it means the same, add alone linguistically implies a mathematical function. This has been a cause of some controversy of std::string::operator+() since + implies a mathematical function not a push char or const char* or another std::string object to the end of the current std::string.3.) A lot of the names of functions or member variables seem unintuitive. Perhaps this is due to my unfamiliarity with the language, but to provide one specific example: vector.push_back, why push_back? Why not add?
On a side note, I agree that some instances of naming confuses me like std::vector::empty() or any of the standard containers' empty() functions. It returns true if the container is empty, which should be named std::(container)::is_empty(). At first I thought it was a statement saying ( make this container empty ), but that was what the clear() function does.
Not all of the containers have a "push_back" named function, std::queue just has a push() function for example because you can only push a value onto the queue in one place. Std::list has push_front and push_back since you can "add" to the front or back of the list in constant time. To add a new object anywhere in the containers, you can use insert() which is pretty clear what it does by the name. Push_back is just a convenience function instead of:
Code: Select all
std::vector<int> ints = { 1, 2, 3 };
ints.insert( ints.end(), 4 );
Code: Select all
std::vector<int> ints = {1, 2, 3};
ints.push_back( 4 );
As you said, the functionality is a part of the algorithms library which extends the classes without having to write those functions for each class. One key idiom is the 'Don't Repeat Yourself". This is another controversy of std::string. Some find that the string class is way too bloated and should've just relied on the algorithms "std::find(), std::find_first_of(), ...". The tolower/toupper only do single characters, so if you wanted to transform the entire string to lower/upper case, you'd have to use something like std::transform.4.) Some of the standard library classes lack functionality that I would expect. For example, std::string contains no tolower/toupper functions, another example, vector has no contains function. I know some of this functionality is in algorithm, but why wouldn't it be part of the class?
Code: Select all
std::string str = {Hello, world!};
std::transform( str.begin(), str.end(), str.begin(), tolower );
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: Random C++ questions from a C# programmer
As an example for the __ naming.
The C++ language itself can't determine if a type is trivially copyable. Trivially copyable means that a type doesn't have the T& operator=( T const& ) operator overloaded because the struct/class might just have stack allocated data as opposed to heap allocated data which means a simple memcpy or memmove would work just fine. To get around this, the compiler implementations might have a function call that calls back to the compiler's AST for information about the type. The function in Visual Studio is: __is_trivially_copyable(T).
The C++ language itself can't determine if a type is trivially copyable. Trivially copyable means that a type doesn't have the T& operator=( T const& ) operator overloaded because the struct/class might just have stack allocated data as opposed to heap allocated data which means a simple memcpy or memmove would work just fine. To get around this, the compiler implementations might have a function call that calls back to the compiler's AST for information about the type. The function in Visual Studio is: __is_trivially_copyable(T).
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com
-
- Posts: 16
- Joined: October 30th, 2017, 11:50 pm
Re: Random C++ questions from a C# programmer
Thanks for the excellent response. I guess I have been spoiled by C#. It possesses a degree of orthogonality that often allows me to guess how something will work without looking it up. In fairness, C++ is much less familiar territory.
-
- Posts: 4373
- Joined: February 28th, 2013, 3:23 am
- Location: Oklahoma, United States
Re: Random C++ questions from a C# programmer
I was unsuccessful in my getting to know C# or maybe just the .NET framework. I felt restricted or lost, but then again i never looked up any tutorials on the matter either. My point was it wasn't very intuitive to me.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com