可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm supposed to implement a function which compares two strings simliar so strcmp
but ignoring whitespace characters, so
strcmpignorews("abc ", " a b c")
should give the same result.
Here's my implementation:
namespace {
void SkipWhitespace(const char *&s) {
for (; std::isspace(*s, std::locale::classic); ++s);
}
}
int strcmpignorews(const char *s1, const char *s2) {
for (; *s1 != '\0' && *s2 != '\0'; ++s1, ++s2) {
SkipWhitespace(s1);
SkipWhitespace(s2);
if (*s1 != *s2) {
break;
}
}
return (*s1 < *s2) ? -1 : ((*s1 == *s2) ? 0 : 1);
}
Now, the question is, would it make sense to inline the SkipWhitespace function? I think I've read somewhere that inline
should not be used for functions which contain loops or switches but I can't remember where and why.
回答1:
Historically, Inline has been an indication to the compiler that it should insert the function body into the call site. However, that is no longer a meaningful annotation. Modern compilers will inline a function or not regardless of the presence or absence of inline
qualification.
To emphasize, whether compiler will perform inline optimization is completely out of your hands.
In modern use, inline has only one function. It can be used to get the linker to ignore multiple symbols, as when a function is defined in multiple compilation units. This technique can be used to break circular dependencies. Use inline for no other purpose.
回答2:
I wouldn't say it shouldn't be used under those circumstances but the act of inlining code will have a larger benefit if the code is relatively quick.
That's because inlining gets rid of the overhead of a function call. If a function call and return takes one second but the code you're inlining takes ten minutes, you're not going to see a huge improvement. But, if the code you're inlining also takes one second, you'll basically double its performance.
Just keep in mind that inline
is a suggestion to the compiler, one it can freely ignore if it figures out you're wrong or even if it's just being obnoxious. I rarely use it and rarely find a need for it, relegating it to the same category as auto
and register
(at least in C).
回答3:
The inline
keyword has always been a mere suggestion for the compiler. That means that if the compiler so chooses then it may ignore the suggestion. On top of that, if the compiler can inline a function it may inline the function even if you didn't ask it to do so.
That said, in order for the compiler to inline a function it must know the function's body. If the function is defined in a separate compilation unit then the compiler probably doesn't know the function's definition outside that compilation unit. In this case the compiler can only inline the function in callers within the compilation unit that defines the function. So the point to take from that is that if you want to allow the compiler to inline a function then you must define the function in the class definition or add the inline
keyword and define it in the header. Inline functions don't violate the ODR.
Another consideration you should make is that because inline functions must reside in a header, and because headers are typically included by a number of compilation units, inline functions increase static coupling. That means that changing the definition of an inline function will cause a cascade in compilation through all dependent compilation units. This is important: a function's definition is not supposed to be part of the interface, but inline functions force this coupling.
For that last point alone, at the end, I'd say never inline a function. That is, until you are irritated enough by the runtime performance of your application or library, at which point you should run your profiler to see if any particular functions would boost performance inlined. Inline functions can also reduce the executable's size if inlining them results in a smaller object code than code necessary for generating a function call, but that's less a significant decision factor in most but few (embedded?) contexts.
The profiler can tell you that a particular function can boost performance if it's inlined, but it can't tell you if a particular inlined function can boost performance (size, runtime, development, ...) if it's un-inlined.
回答4:
In general, Profile before inlining.
Inlining is always a suggestion to the compiler. It retains the right to ignore you or agree with you. It may be inlining other parts of your code without your permission anyway.
If you don't mind extra typing, here are some guidelines for declaring a method or function as inline:
- The content of the method uses less
than or equal to the instruction
cycles for calling, initializing,
cleaning up and returning from the
method.
- The method has no jumps, or branches
to other methods.
- The method has no loops (nowadays,
small loops can fit into a
processor's cache).
- The method only uses methods that
are inlined or can be inlined, this
includes library functions.
- You're converting a macro
(
#define
).
- The method passes the above tests
(except 5), and is thoroughly
tested. (Can you say rebuild all
dependencies because you changed a
header?)
My style is to inline class getters & setters. Any code that is volatile (either not working or subject to change) or is complex will not be inlined.
回答5:
In the context, there is no harm and possibly some good in using inline
.
There are limits on the complexity of a function that the compiler will inline; functions with complex loops or switches are more likely to reach that limit than functions without. So, what you read isn't all wrong; it just needs to be qualified.
Stylistically, I'd use a while
loop in place of your for
loop:
while (isspace(*s, std::locale::classic))
++s;
This also fixes the bug in your code which only skips characters that are not white space characters. (The bug was fixed while this answer was typed!)