Okay, finally in a place where I can respond, I have been kind of chuckling at this thread as I have been reading it from my phone. On Wed, Apr 28, 2010 at 2:55 PM, Piotr Jachowicz <pjachowi@gmail.com> wrote:
On 28 April 2010 10:02, Pete Bartlett <pete@pcbartlett.com> wrote:
Piotr Jachowicz wrote:
"Cases like that promote stereotype "It's better to avoid Boost because it contains many traps"
Hi Piotr,
I hope that when you have absorbed the comments of others, and understood that a const char* is a pointer and a std::string is object and so of course they have behave differently under copying, then you will come back and disown the above comment. Otherwise a false "slur" against Boost will remain on the internet forever, which is unfair to its authors.
Ok, it looks that my perception of "easy to be misused" differs from yours. Nothing wrong with that.
No, the perception of "easy to be misused" is based on the C++ standard, hence it is an issue with your erroneous perception of not knowing C++ rules. It is (as I recall) defined in the standard that the c_str() member returned by an std::string's lifespan is only until the next termination point (generally a semicolon in C++). This function returns a "const char*", hence the pointer it returns can be considered worthless after the next termination point (especially since if you set the string to a string that was, oh, 50 characters long, then what pointer it returns could be deallocated, hence you can access deallocated memory if you saved it somewhere and tried to access it). In real life, the pointer is valid as long as the std::string is not reassigned in every STL implementation that I know of. Thus, in this example: """ void f2(const char* s) { cout << s << '\n'; } function<void()> make2(const string& s) { return bind(f2, s.c_str()); // line A } """ On line A you create a bound struct, basically what you do is the same thing as this: """ struct myBoundOp { const char *ptr; function<void(const char*)> fun; void operator()() { fun(ptr); // line C } } void f2(const char* s) { cout << s << '\n'; } function<void()> make2(const string& s) { myBoundOp bound; bound.fun = f2; bound.ptr = s.c_str(); // line B return bound; } """ So, on line B, you assign the pointer to the buffer in the std::string to a long-term pointer. Now, when you call the returned function, it will call line C, if what the pointer is pointing to changed, well it should be obvious what happens, just normal C++ (or heck, even C or assembler, nothing special here). Now, let's see if it with f1, that takes an std::string, but still as a pointer: """ struct myBoundOp { std::string *ptr; function<void(std::string*)> fun; void operator()() { fun(ptr); } } void f2(std::string* s) { cout << *s << '\n'; } function<void()> make2(const string& s) { myBoundOp bound; bound.fun = f2; bound.ptr = &s; // line D return bound; } """ Now, on line D, you are storing the pointer to the std::string itself, instead of its buffer, but hey, if you change the string before you call the callback, same thing will occur as what is going on with the c_str method. Now, if we try to do this with a std::string *object*, instead of a pointer: """ struct myBoundOp { std::string str; function<void(std::string)> fun; void operator()() { fun(str); } } void f2(std::string s) { cout << s << '\n'; } function<void()> make2(const string& s) { myBoundOp bound; bound.fun = f2; bound.ptr = s; // line E return bound; } """ Hey now, line E just caused the copy constructor to be called, doing something very different now! If you look, it made a copy of the object, so if you edit the original, the function will still be called with the copy. On Wed, Apr 28, 2010 at 2:55 PM, Piotr Jachowicz <pjachowi@gmail.com> wrote:
I only wanted to express concern that when binding to function accepting pointers (which is misuse) would cause issue in production code, then it can be seen as "problem with boost". Similar as problems with copy/owning semantic in CORBA to C++ mapping are often summarized as "problem with CORBA". I've observed it at very high decision level in big IT company.
I do not believe that using pointers with function pointers is a mis-use, I use them all the time, including in fancy things like Boost.Phoenix, but I also understand C++, it might behoove you to study more about how C++ works and its rules on things, which are very much how assembler does it, if you learn assembler (even an old/easy dialect), then it will forever help you in C/C++.