I thought it might be interesting to hold a discussion from time to time about a given code snippet. Things that some may find enlightening and others can share their views, critiques, and recommendations. This will be my first thread of this type but if it seems like a good idea, I might follow up with more every so often. Feel free to join in the discussion. Here goes!
Strings should not be passed with a copy. Instead pass them back as a const reference and let the user of the class decide whether or not they want/need them to be copied.
This snippet fails to compile because p.getId() is an integer, and integers cannot be concated to a string in this fasion. Instead use std::stringstream str; str<<p.getId()<<p.getName()<<p.getCatagory(); return str.str();
This snippet fails to compile because p.getId() is an integer, and integers cannot be concated to a string in this fasion. Instead use std::stringstream str; str<<p.getId()<<p.getName()<<p.getCatagory(); return str.str();
Ah...but it DOES compile!
[650 bash chad@asdf discussion1]$ ls
main.cpp
[650 bash chad@asdf discussion1]$ cat main.cpp
#include <iostream>
#include <string>
class Product {
int id_;
std::string name_;
std::string category_;
public:
int getId() const { return id_; }
std::string getName() const { return name_; }
std::string getCategory() const { return category_; }
//...
Product():id_(10),name_("name"),category_("category") {}
};
std::string createKey( const Product & p ) {
std::string key( "" + p.getId() + p.getName() + p.getCategory() );
return key;
}
int main() {
std::cout << createKey( Product() ) << std::endl;
return 0;
}
[650 bash chad@asdf discussion1]$ g++ main.cpp
[651 bash chad@asdf discussion1]$ ./a.out
namecategory
[652 bash chad@asdf discussion1]$ g++ --version
g++ (GCC) 4.1.1
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[653 bash chad@asdf discussion1]$
As far as I know, casting an integer to a pointer means that its memory address is the value of the integer, not a string representation of the integer or the integer itself...
char* ch = (char*)123;
ch points to a character at memory slot 123, but that could just be random memory!
As far as I know, casting an integer to a pointer means that its memory address is the value of the integer, not a string representation of the integer or the integer itself...
which is why there is no 10 in his output.
"" + p.getId() + p.getName() + p.getCategory()
We know that a + has the same precedence as +, so this is equal to
((("" + p.getId()) + p.getName()) + p.getCategory())
which is
( ( ( const char* + int ) + string ) + string )
You get "Whatever the address of "" is in memory" + some integer offset. Which is garbage...In fact, I got a random debug message >_> "This operation will not affect the quality of the optimized code..." XD
It could, but then there was garbage when he changed 10 to 'A'.
See how much garbage there is yourself for( int i = 0; i < 80*25-1 ; i++) std::cout << *(""+i);
This gives your compiler all kinds of optimization options, and significant speed issues where relevant. (This assumes, of course, that the integer problem already discussed above was fixed.)
Of course, you could also cache the key if your user is asking for it a lot more than the constituent values get changed...
You are correct std::string + int will give an error
BUT
You are mistaking what is happeing in the code in original post.
The original post says this: "" + p.getId() + p.getName() + p.getCategory()
Remembering that "" is a char* - what we have is char* + p.getId() + p.getName() + p.getCategory()
What happens is this:
1.
The compiler evaluates the functions - so you you will have char* + int + string + string
2. char* + int is standard pointer math - the pointer is just moved forward.
so char* + int still evaluates to a char pointer.
So the current result is char* + string + string.
3.
There is a global overload in the standard library for char* + string to give a string result.
So what we have now is string + string.
EDIT: Nevermind, I changed some project settings in my compiler and now adding an int to a std::string does convert the int to a char and give no warning message or error. It works like with stringstreams, which is quite scary because I think this functionality should not exist...