const reference of std::locale

C

cinsk

Hi.

On the Gentoo Linux 2.6.28, GCC 4.4.3,

In the class, I want to create a member function 'isspace(char)', so I
tried like:

class parser {
public:
parser() : loc_(std::locale()) {}
bool isspace(char ch) { return std::isspace(ch, loc_); }
...
private:
const std::locale &loc_;
};

parser p;
p.isspace('a'); // throws std::bad_cast or segmentation fault.

Q. Could you explain why it throws a bad_cast?

Then, I modified above constructor in following way:

parser(const std::locale &loc = std::locale()) : loc_(loc) {}

Q. Then, the problem gone. Could you explain why it succeed? What's
the difference from the former?

If I make a global function like std::isspace() using the second
constructor style, it works again.

isspace(char ch, const std::locale &loc = std::locale()) {
return std::isspace(ch, loc);
}

isspace('a'); // works.
 
Ö

Öö Tiib

Hi.

On the Gentoo Linux 2.6.28, GCC 4.4.3,

In the class, I want to create a member function 'isspace(char)', so I
tried like:

class parser {
public:
  parser() : loc_(std::locale()) {}
  bool isspace(char ch) { return std::isspace(ch, loc_); }
  ...
private:
  const std::locale &loc_;

};

This stores reference to temporary when constructed. Anything may
happen when you call member function isspace, since you use that bogus
reference there.
 
V

Vaclav Haisman

cinsk wrote, On 8.10.2010 2:00:
Hi.

On the Gentoo Linux 2.6.28, GCC 4.4.3,

In the class, I want to create a member function 'isspace(char)', so I
tried like:

class parser {
public:
parser() : loc_(std::locale()) {}
bool isspace(char ch) { return std::isspace(ch, loc_); }
...
private:
const std::locale &loc_;
};

parser p;
p.isspace('a'); // throws std::bad_cast or segmentation fault.

Q. Could you explain why it throws a bad_cast?
The code has undefined behaviour. Your loc_ becomes dangling reference at the
point the p variable finishes constructing because the std::locale temporary
goes away. The UB manifests as bad_cast in your case, you were lucky.
Then, I modified above constructor in following way:

parser(const std::locale &loc = std::locale()) : loc_(loc) {}

Q. Then, the problem gone. Could you explain why it succeed? What's
the difference from the former?
It is not gone, it is just masked somehow. Your loc_ still becomes dangling
reference after the parser construction end.
If I make a global function like std::isspace() using the second
constructor style, it works again.

isspace(char ch, const std::locale &loc = std::locale()) {
return std::isspace(ch, loc);
}

isspace('a'); // works.
This works because the std::locale temporary constructed for the second
parameter lives through out the whole isspace() call.
Change the loc_ member type from const std::locale& to plain std::locale.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,954
Messages
2,570,116
Members
46,704
Latest member
BernadineF

Latest Threads

Top