问题
I have string constants, for strings that I use in multiple places in my app:
namespace Common{
static const std::string mystring = "IamAwesum";
}
When posting a question about something else (What happens to a .h file that is not included in a target during compilation?), another user made the following comment :
be aware that your static string are global in this case. So they are could create an exception at anytime and can't be catch. I advise you to use function who return a reference of your string. std::string const &mystring { static std::string const mystring = "IamAwesum"; return mystring} by this way your object is only construct when needed
Can someone explain why using static const strings in the manner that I do so above, risks throwing exceptions ?
回答1:
N4140 § 3.6.2 [basic.start.init]/ 4
It is implementation-defined whether the dynamic initialization of a non-local variable with static storage duration is done before the first statement of
main
.
N4140 § N4140 15.3 [except.handle]/ 13
Exceptions thrown in destructors of objects with static storage duration or in constructors of namespace-scope objects with static storage duration are not caught by a function-try-block on
main()
.
You simply cannot catch an exception generated by the string's constructor - say, std::bad_alloc
.
(opinion) That being said, for such small strings I find this kind of consideration to be paranoid.
回答2:
The pdf document mostly refers to exceptions from the object ctor and initialization order fiasco with static or dynamically linked libraries.
The only danger I see in your code for exceptions is if the ctor of std::string will throw when it is called.
If you want to really be on the safe side you can use static const char* mystring instead which will not call to a C++ ctor.
There is also the matter of the code being in a shared library which then needs to be placed in the address space of the process. I don't see that as a major problem if you don't use complicated ctors(ctors that can throw).
回答3:
The only "issue" -- if you can call it that -- which I see with your code is that you are being wasteful by needlessly copying data that is already constant into a dynamically allocated buffer (which is formally constant, but not in reality). This uses twice as much physical memory as necessary and does a needless copy.
Does it matter? Almost certainly, no. Even on a "rather limited memory" system, this will nowadays hardly be noticeable, neither from an execution time point of view, nor by its memory consumption.
As for exceptions, it is of course technically true that the allocation that std::string
has to make could fail, and therefore the constructor could throw, and you wouldn't be able to catch it. But please be realistic.
This is almost guaranteed not to happen, but even if it does... if something as trivial as allocating memory for a couple of string fails while your program starts up, you have a really, really serious issue on a completely different scale!
Besides, as pointed out in a comment on another answer above: Assuming this does happen, what are you going to do about it? The program is utterly unable to run, so there's not much short of killing the program that you could conceivably do.
Now, with C++17 not being far away and string_view
already being available in std::experimental
on several mainstream compilers, there's another thing you could try: Use the correct thing.
A string_view
will, contrary to a string
, not allocate non-constant memory, copy constant data into that, and then pretend it's constant. Instead, it will manage a pointer directly to the constant data, and that's all.
That way, your constants are truly (not just formally) constant, there are no allocations, no possibility of exceptions, and no double memory usage. And for the most part, it still looks and smells like a string
. The only notable differences being that a string_view
doesn't guarantee nul-termination (but the character constant it points to does, so this is irrelevant), and the fact that it's really constant, not modifiable... which is exactly what you want.
来源:https://stackoverflow.com/questions/40377546/why-can-creating-a-static-const-stdstring-cause-an-exception