Quote:Original post by OneMoreToGo
I have a book on C++, and although it never mentioned the std:: operator (neither did the course I took, I swear! And everything worked too!) it seems fine in all other regards, so I'll go back and review arrays & pointers. I've googled a bit about string operators, and they seem useful. Do they comply with standard sizeof() & strlen() commands? I'll just test that myself though, so no worries.
To be able to use things correctly, you have to know what they are. Talking vaguely about "operators" and "commands" probably has a lot to do with why you're confused. Also, your C++ book is evidently several years out of date and needs to be thrown away, and most C++ programming courses out there that I've heard about are pretty much garbage as well. Sorry, but that's the state of things.
std:: is a namespace. Namespaces are a way of decorating identifiers (that's a catch-all term that includes variable names, function names and class/struct names - and probably other stuff I forgot) so that instead of using "foo_" prefixes to avoid name collisions, you use "foo::". But it's actually much better than that, because (a) they're a language construct that the compiler can actually do some checking with, and (b) you can set things up such that certain blocks of code omit the "foo::" for convenience, when it is not needed to avoid collisions. For example, suppose you made a "2d vector" class (of the sort that is reinvented a gazillion times by everyone; basically it just represents a pair of X and Y coordinates), and called it 'vector', and wanted to store a std::vector of them. In the code using that vector, you'd have to write "std::vector<vector>", in order to make things clear to the compiler. (Perhaps you would be smart enough to put your vector class in its own namespace, too; then you'd qualify that name as well.) But in some other source file of the same project that *didn't* use the local vector class but still used the standard library vector container, you could get away with "using std::vector;" at the top and "vector<int>" everywhere else.
'std::string' is a class. Thus you can declare variables of type std::string; each of these might be called "a std::string instance" or "a std::string object". It represents textual information. In C++, classes and structs can provide "member functions", as well as operator overloads . When you write "cout << foo;", 'cout' is a global object of type std::ostream, and you are invoking the overloaded operator<<(std::ostream&, T) for T = whatever type 'foo' happens to have. This is the same sort of process as when you write "foo + bar" and it invokes operator+(int, int) (except that there isn't really such a function in a library somewhere; the compiler just directly emits the appropriate machine code) if foo and bar are both ints, or operator+(const std::string&, const std::string&) if foo and bar are both std::strings. Note that the operator+ in question yields another std::string object which represents the concatenation of those two input strings. You can't directly, or even with a relatively small amount of work, do that properly with char*'s.
A single-quoted string in your program, like 'a' or '\n', is a "character literal". That is to say, a single byte value. (Back when all this stuff was designed, "characters" and "bytes" were considered equivalent. Now that we have Unicode, huge monkey wrenches are thrown in to that system.) It's a value that could be assigned to a variable of type char, which is an integral numeric type. When output, the numeric value is translated into a character via the ASCII table.
A double-quoted string in your program is a "string literal". What happens when you write that is that the compiler embeds the contained sequence of characters into the executable's data segment, and puts a zero-valued character ('\0') at the end as well. Then, in an expression using the string literal, that literal becomes a value of type char* (pointer to char), which points at (has a value which is the memory address of) the beginning of that sequence of characters. So a string literal is a completely different thing from a character literal, even if the string happens to be only "one character long" (note that actually two bytes are used in the static storage, because of the aforementioned 'null terminator').
sizeof is an operator. It yields, *at compile-time*, the number of bytes that are needed to represent the provided variable or type, using the *static* type.
Note that a character *array* is different from a character *pointer* - in a few ways. You need to read
this. Example:
#include <iostream>using namespace std;int main() { char foo[16]; char* bar = foo; // that causes bar to point to the beginning of the foo storage cout << sizeof(foo) << ' ' << sizeof(char[16]) << ' ' << sizeof(bar) << ' ' << sizeof(char*) << endl;}
You *can* use sizeof() on any variable or type, but it is rarely something that a beginning programmer ought to find useful.
strlen() is a function. It accepts a specific argument type (const char*), so that's all you can pass to it. It's intended for figuring out the length of a "string" represented by a char*, in the way that string literals represent things. It does this by checking character values, starting at the provided location and advancing forward through memory, until it finds a zero byte (such as the one automatically inserted at the end of a string literal).
The std::string object does provide a way to extract a const char* representing its internal buffer: its .c_str() member function. This allows you to pass the data to some C APIs. However, you would not want to do it with strlen(), for at least three reasons:
1) It would be terminally retarded to do so, because the std::string object already provides a function that does that directly: its .length() member function.
2) You would lose efficiency: the std::string object already includes a length count, which is only updated when something happens that might change the string length, so all its .length() member does is return the value there. By contrast, calling strlen() requires searching through memory over the entire length of the string - every time you call it, because the information didn't get remembered anywhere.
3) You could get a wrong answer, because std::strings are capable of holding zero bytes within the "real" string data, whereas char* strings basically aren't - if you tried to make a string "hello\0world", then strlen() would stop at the *first* \0 it saw, and report a length of 5, as if all you had was "hello".