So today I wrote a fairly hard to find bug where I initialized a std::string to nullptr (not a pointer to std::string, but the value itself). I've found apparently it's only possible to do in C++11 or later with clang.
#include <string>
#include <iostream>
using namespace std;
class Meh{
int x;
};
class Foo
{
private:
std::string x=nullptr;
Meh y=nullptr; //remove this line and it compiles
public:
std::string z=nullptr;
};
int main(void)
{
Foo f;
cout << f.z;
return 0;
}
As you can see, I tried assigning nullptr to just a random instance of a class and it didn't work. What magic is in string that allows this to work, and in what way is this even valid syntax? I assumed I would be met with a type casting error in this case.
For reference I compiled with this:
clang++ test.cpp -O3 -g -fno-inline -std=c++11 -Wall
It gave no form of warnings, though it would error out if not using C++11
That's simply because there are constructors (number (5) in the link) and assignment operators (number (3) in the link) for std::string that accept a const char*, and hence the nullptr matches.
Before C++11 (and therefore before nullptr), the same problem occurred when you tried to construct from 0 or NULL. All those cases were illegal and result in undefined behaviour, although at least one STL (RogueWave?) accepted it in the past and generated an empty string.
Related
I have a little piece of code in C++:
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main() {
int i=0;
istream_iterator<string> EOS;
double x;
return 0;
}
Now i compile it with my g++ (GCC) 4.4.4
g++ -W -Wall -pedantic test.cc -o test
And get:
test.cc: In function 'int main()':
test.cc:9: warning: unused variable 'i'
test.cc:11: warning: unused variable 'x'
Why there is no warning for unused EOS?
It is not a primitive value, so its constructor and/or destructor might have desired side effects.
To illustrate that this happens in practice: I use a class to time sections of code, that looks roughly like this:
class Timed {
double start;
public:
Timed() { start = now(); }
~Timed() { std::cout << (now() - start) << '\n'; }
}
So to measure how long a function takes, I simply do:
void slow() {
Timed t;
// heavy operation here...
}
The variable t never gets used, but it's still important to the behaviour of the code.
istream_iterator<string> has a constructor, so the declaration of EOS isn't really a no-op like the declarations of i and x are.
Often you want to declare a class-type object and then not do anything with it. For example, consider std::lock_guard in C++0x (boost::scoped_lock in Boost) or any other kind of scope guard class. You don't usually want to do anything with that kind of object, you just want to create the object so that its destructor get run at the end of the block to perform whatever cleanup needs to be performed.
Because you could have done that with a purpose. It's not a primitive. Maybe the constructor and destructor do something important?
MFC even had classes that operated that way, you could do this:
void foo()
{
CWaitCursor cursor;
[...]
}
That would display an hourglass icon for the duration of the function.
I have a little piece of code in C++:
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main() {
int i=0;
istream_iterator<string> EOS;
double x;
return 0;
}
Now i compile it with my g++ (GCC) 4.4.4
g++ -W -Wall -pedantic test.cc -o test
And get:
test.cc: In function 'int main()':
test.cc:9: warning: unused variable 'i'
test.cc:11: warning: unused variable 'x'
Why there is no warning for unused EOS?
It is not a primitive value, so its constructor and/or destructor might have desired side effects.
To illustrate that this happens in practice: I use a class to time sections of code, that looks roughly like this:
class Timed {
double start;
public:
Timed() { start = now(); }
~Timed() { std::cout << (now() - start) << '\n'; }
}
So to measure how long a function takes, I simply do:
void slow() {
Timed t;
// heavy operation here...
}
The variable t never gets used, but it's still important to the behaviour of the code.
istream_iterator<string> has a constructor, so the declaration of EOS isn't really a no-op like the declarations of i and x are.
Often you want to declare a class-type object and then not do anything with it. For example, consider std::lock_guard in C++0x (boost::scoped_lock in Boost) or any other kind of scope guard class. You don't usually want to do anything with that kind of object, you just want to create the object so that its destructor get run at the end of the block to perform whatever cleanup needs to be performed.
Because you could have done that with a purpose. It's not a primitive. Maybe the constructor and destructor do something important?
MFC even had classes that operated that way, you could do this:
void foo()
{
CWaitCursor cursor;
[...]
}
That would display an hourglass icon for the duration of the function.
typedef unordered_map<string, relationNode*> relationMap;
using relation_entry = relationMap::value_type;
void insertNode(string category, relationNode* node) {
relation_entry insertPair =
make_pair<string, relationNode*>(category, node);
}
causes an error of "cannot convert 'category' (type 'std::string(aka std::basic_string(char))') to type 'std::basic_string(char)&&"
and an error of "cannot convert 'node' (type 'relationNode*') to type 'relationNode*&&".
I was planning to make the pair then insert it into a unordered_map.
I am using "g++ -g -O0 -Wall -Wextra -std=gnu++11" to compile the code. Any help will be greatly appreciated.
Just write:
relation_entry insertPair =
make_pair(category, node);
This will work and be more concise (in fact, that's the reason you use std::make_pair instead of calling the constructor directly in the first place).
You should know that this is a backward-compatibility issue with C++11. Consider this piece of C++98 code (I replaced unordered_map with map and using with typedef):
#include <map>
#include <string>
using namespace std; // just for testing
struct relationNode {};
typedef map<string, relationNode*> relationMap;
typedef relationMap::value_type relation_entry;
void insertNode(string category, relationNode* node) {
relation_entry insertPair =
make_pair<string, relationNode*>(category, node);
}
int main() {
}
Go to http://cpp.sh/ and try to compile it. You will see that it compiles fine in C++98 mode but not in C++11 and C++14 modes.
For a detailed explanation of the issue, see C++11 make_pair with specified template parameters doesn't compile
Bottom line: Don't specify redundant type arguments and you'll be fine.
Let's look at such piece of code:
#include <iostream>
int foo(int i) {return i; }
int foobar(int z) {return foo(z);}
int main() {
std::cout << foobar(3) << std::endl;
}
It compiles fine with g++ -std=c++11 ... and gives output 3. But The same output is given by:
#include <iostream>
int foo(int i) {return i; }
int foobar(int z) { foo(z);}
int main() {
std::cout << foobar(3) << std::endl;
}
It compiles without problems but clearly the keyword return is missed in foobar. Is it a bug in gcc 4.8.3 or maybe I'm not aware of some c++11 principle? (Runned on Fedora 20)
The C++ standard doesn't make a mandate for compilers to insist on a return-statement in functions return non-void. Instead, flowing off the end of such a function without a return-statement is undefined behavior. The relevant statement in the standard is in 6.6.3 [stmt.return] paragraph 2, last sentence (and in 3.6.1 [basic.start.main] paragraph 5 is the statement making it OK for main() to flow off this function):
Flowing off the end of a function is equivalent to a return with no value; this results in undefined behavior in a value-returning function.
The primary reason for this approach is that it may be non-trivial or even impossible if the function actually ever really returns. Consider this function declaration and function definition:
extern void will_always_throw();
int does_not_return_anything() {
will_always_throw();
}
Assuming will_always_throw() indeed does as the name suggests, there is nothing wrong. In fact, if the compiler gets smarter and manages to verify that will_always_throw(), indeed, always throws (or a "noreturn" attribute is attached to will_always_throw(), it may warn about the last statement in this definition never being reached:
int does_return_something_just_in_case() {
will_always_throw();
return 17;
}
The general approach to deal with these situations is for compilers to support suitable options enabling/disabling warnings as necessary. For example, on your code all compilers I have access to (gcc, clang, and icc) create a warning assuming warnings are enable (using -Wall for the first two and -w2 for Intel's compiler).
The code compiles fine because it is well-formed, and so you can run it. But since this is undefined behavior, you cannot rely on any behavior of the program, anything is legal. To prevent accidents like this, enable compiler warnings. if you compile your code with -Wall, you will see
main.cpp:10:28: warning: no return statement in function returning non-void [-Wreturn-type]
int foobar(int z) { foo(z);}
Here you can get more information about those warnings. Use them and make sure your code compiles warning free. It can catch a lot of errors in your code at compile time.
I have a little piece of code in C++:
#include <iostream>
#include <iterator>
#include <string>
using namespace std;
int main() {
int i=0;
istream_iterator<string> EOS;
double x;
return 0;
}
Now i compile it with my g++ (GCC) 4.4.4
g++ -W -Wall -pedantic test.cc -o test
And get:
test.cc: In function 'int main()':
test.cc:9: warning: unused variable 'i'
test.cc:11: warning: unused variable 'x'
Why there is no warning for unused EOS?
It is not a primitive value, so its constructor and/or destructor might have desired side effects.
To illustrate that this happens in practice: I use a class to time sections of code, that looks roughly like this:
class Timed {
double start;
public:
Timed() { start = now(); }
~Timed() { std::cout << (now() - start) << '\n'; }
}
So to measure how long a function takes, I simply do:
void slow() {
Timed t;
// heavy operation here...
}
The variable t never gets used, but it's still important to the behaviour of the code.
istream_iterator<string> has a constructor, so the declaration of EOS isn't really a no-op like the declarations of i and x are.
Often you want to declare a class-type object and then not do anything with it. For example, consider std::lock_guard in C++0x (boost::scoped_lock in Boost) or any other kind of scope guard class. You don't usually want to do anything with that kind of object, you just want to create the object so that its destructor get run at the end of the block to perform whatever cleanup needs to be performed.
Because you could have done that with a purpose. It's not a primitive. Maybe the constructor and destructor do something important?
MFC even had classes that operated that way, you could do this:
void foo()
{
CWaitCursor cursor;
[...]
}
That would display an hourglass icon for the duration of the function.