Could someone tell me what's the purpose of declaring static functions outside classes? What's the difference between this 2? Are there any benefits for using static in this situation?
static void someRandomFunction();
int main()
{
someRandomFunction();
return 0;
}
and
void someRandomFunction();
int main()
{
someRandomFunction();
return 0;
}
At namespace scope, static gives a name internal linkage, meaning that it is only accessible within the translation unit that contains the definition. Without static, it has external linkage, and is accessible in any translation unit.
So you'd use static (or, alternatively, an unnamed namespace) when writing a function that's only intended for use within this unit; the internal linkage means that other units can define different functions with the same name without causing naming conflicts.
Non-static functions (and global names in general) are better declared in a header, to make sure that every translation unit that uses them gets the same declaration.
The static keyword on global functions or variables limits the visibility and linkage scope of the function or variable to the current translation unit.
That means that for a function, it can only be called from the current source file, and not from other source files.
A static function remains visible only in file scope. This is a C feature.
The recommended way to do it in C++ is using an anonymous namespace, as in:
namespace // no name, i.e. anonymous
{
void someRandomFunction();
}
int main()
{
someRandomFunction(); // visible only within this file.
return 0;
}
Note that the function body also has to be declared somewhere within the same file since the linker will not try to find it in other (external) translation units.
So void someRandomFunction(); is really a forward declaration for a function that is defined elsewhere in the same file (i.e. in the same translation unit).
If the function is actually called, you will get a linking error unless the function body is defined in the same file.
(The more pedantic technical term is actually not file but translation-unit since the body might be in an #includeed header do not in the actual file per-se. )
static void someRandomFunction();
This has to be used within same compilation unit (source file) and outside that compilation unit, not available for use.
Whereas, if you have
void someRandomFunction();
with one definition acrosss the program, the function can be used by any compilation unit globally across the program
Static methods and static functions are entirely different things.
Static methods are methods of a class instead of an instance (which you already know, as it seems).
Static functions, on the other hand, are function which are available only in the module they are defined in. They are not exported and cannot be put in a header file and used in another c file. This way you can write different functions sharing the same name, and also the compiler may optimize your code more thoroughly by inlining the function, knowing that no other file is dependant on it.
static tells the compiler not add the function to the symbol table for the object file. This effectively means that the linker is unable to find the function which in turn means you can only use the function directly in the current compilation unit. You can however call static functions from another compilation unit if this is done through a function pointer.
Related
The way I think of inline in C++ is for linkage/scoping. I put it in the same basket with extern and static for global objects.
Typically for a function implemented in a header file, my go-to solution would be to make it static:
// In Foo.h
static void foo()
{
// Do stuff...
}
However, I believe this is also valid and does not seem to violate ODR:
// In Foo.h
inline void foo()
{
// Do stuff...
}
What are the semantic differences between the two? Also I'm not exactly sure what areas of the C++ standard would explain exact differences, or if it's just undefined and differences lie with the implementation.
inline conveys exactly what you want: "please suppress the ODR (One Definition Rule) for this function, so that each translation unit can (and must) supply its own copy of the function's definition".
The compiler will then either inline calls to the function, or merge together the function definitions from different TU's (so that the resulting function exists once in the executable).
static, on the other hand, tells the compiler to generate the function in every translation unit where it is defined, and just not share it. So you end up with an arbitrary number of technically separate functions existing in the resulting executable.
In a nutshell, if you use static, then taking the address of the function in different translation units will return different addresses (because you're telling the compiler to generate a function in each TU), but if you use inline, they'll show the same address (because you're defining one function, and just telling the compiler to merge the many definitions together).
The main difference is what happens with any static locals in the function -- if the function is static then each compilation unit will have its own copy of the static locals distinct from any other compilation unit. If the function is inline, there will only be one (set of) static local(s) shared by all compilation units.
In many cases you will not notice a difference because compilers and linkers are pretty smart these days.
However, an inline function must behave as-if it was a regular function.
A static function in a header will get compiled into every source file which includes it - so there will be lots of copies of it.
Mostly, this doesn't matter much, but there are a few ways it does.
An inline function has one address.
Static functions will have a different address in each translation unit.
Static-local variables: WIth the inline, there will be a single copy of them.
With static-functions, there will be a unique copy of each static-local variable for each translation unit that includes that function.
Thinking about this question from the original intents of keywords inline and static may be more helpful and clear.
inline functions
The original intent of keyword inline is to improve runtime performance, not for linkage/scoping as you said at the beginning. It is a hint that makes compiler attempt to generate code inline at the calling point rather than laying down the code once and calling it every time, which can avoid some overheads such as creating stack frame for the calls. In order to generate code inline, the function definition must be in scope, not just the declaration like ordinary functions. So, you should put the whole function definition in a header file foo.h, and #include "foo.h" when call it. These inline functions in different translation units must be identical token-by-token to obey ODR(One Definition Rule). And these all inline functions are just one single function, and so do static variables in this inline function.
static functions
Keyword static can be used to make functions local to a translation unit, namely that it gives them internal linkage. So if you put the whole function definition of foo() into a header file foo.h and mark it as static, all translation units which #include "foo.h" will have a local function foo(). In other words, the functions foo() in different translation units are not one single function, and neither do the static variables in these static functions.
static inline functions
So you can guess functioins marked by both static and inline. These are not the same functions in different translation units like static functions, but can give performance improvement by generate code inline.
No one seems to be mentioning that in C++, a static function is one that is called directly, not on an instance of the class. In other words, there is no implicit "this" pointer. If function foo of class MyClass is static, you say:
MyClass::foo(); // calls it
and not:
MyClass an_object = new MyClass();
an_object->foo();
Can anybody explain difference between static function defined within class and static function declared e.g. in file.hpp and defined in file.cpp (I can only use this static function within this file ?
Can anybody explain difference between static function defined within class
That means the function is class-wide, and doesn't need to operate on a particular object. In other words, for that function there is no this.
and static function declared e.g. in file.hpp and defined in file.cpp (I can only use this static function within this file ?
That means that that function does not have external linkage, which means other compilation units (i.e. object files) cannot link to it, because it's not in the symbol table.
Thanks for your reply but could you explain why other compilation units cannot link to it ?
First, some terms. Technically, the compiler is just the part that generates object code from source code. The linker later takes a set of object files and "links" them to make the final program.
To make this work, the compiler generates a "symbol table" and puts it in the object file along with the compiled code. This symbol table lists both the symbols for the global variables and functions in the file, as well as the external symbols that code needs to be linked to in order to work.
The linker's job is to read all the object files and match symbols needed by each object file to symbols provided by other object files. If everything is successful, and there aren't any unresolved needed symbols, the link succeeds and you get your program.
What static on a function or global does is simply tell the compiler to not put that symbol in the object file's symbol table. Nothing else; that symbol is still perfectly usable within that same source file. The linker simply never sees the symbol, and thus cannot link anything to it.
Class members cannot be "disappeared" in this manner, so static has a different meaning in the context of a class. (This recycling of the keyword was probably done to avoid adding another reserved word to the language. BTW, Objective-C solved this same problem in a different manner, using the + and - tokens.)
(And static can have yet another meaning when applied to variables declared inside functions or methods, as Mike points out below. In that case it's basically a global variable, but private to the function.)
Could you also explain why inline functions are implicitly defined as static ?
Since inline functions do not exist as independent pieces of code (they are instead merged "in line" into the calling function), they cannot have symbol table entries (there's nothing to link to).
Please refer to this link
A static variable inside a function keeps its value between invocations.
In C++, however, static is also used to define class attributes (shared between all objects of the same class) and methods. In C there are no classes, so this feature is irrelevant.
There is no difference between a static function defined in the global scope, no matter if it's in a header file or in a source file. Unless the header file isn't included anywhere, when the functions in it is never really defined anywhere.
Then phrase you need to learn when talking about static (non-member) functions is translation unit. A translation unit is a source file and all header files included in that source file, after the preprocessor have processed the file and is the actual input to the compiler. A static function is local to the translation unit, which is why there is no difference if it's defined in the source file or a header file.
You can also use an anonymous namespace to define functions, and they will be local to just the translation unit the anonymous namespace is in.
Also note that functions defined as inline are implicitly defined as static as well.
A static member function is part of the class, and can access static member variables without scope prefix. They do of course have to prefixed with the scope of the class to be called. The difference between a static member function and a non-static member function is that static member functions are not part of any specific instance of the class, and so have no this pointer. If you want to access a specific class instances member variable, you have to pass the instance to the static member function through an argument.
I have a function which should be included in two different translation units (i.e. cpp files) from a common header.
I might use an anonymous namespace to have this function included in both TUs without conflicts but I'm wondering what would be the best way to accomplish this (static? I don't think global could work, multiple definitions)
If you want it to be the same function in every TU, use inline. That's exactly what inline is for: shared functions defined in headers.
In the admittedly-unlikely event that you want it to be a different function in every TU, use either an unnamed namespace or static. I don't think the standard gives an official view which one is preferred in C++, but you kind of get the impression it's the unnamed namespace.
Which one you want depends on why you're putting a function definition in a header file in the first place, and how you intend the header to be used.
You need to learn the difference between declaration of function and it's definition. Except of template and inline functions only function declaration should be in a header file, function definition should be in translation unit.
void foobar( int ); // this is function declaration, now you can call this function
// you can put it on your sources as many times as you want
void foobar( int param ) { // this is function definition, it should appear only once
...
}
If you want that the compiler would consider this function as a different function in each CU you can include its definition in an unnamed namespace. According to the C++ 2011 Standard entities declared in unnamed namespaces have internal linkage.
Can anybody tell me what the difference is between an inline function and static inline function?
In which cases should I prefer static inline over inline?
I am asking this question because I have an inline function for which I am facing compilation issues during linking (relocation error:... symbol has been discarded with discarded section ...). I made it a normal function and it worked.
Now some of my seniors told me try with static inline.
Below is my function:
inline void wizSendNotifier (const char* nn_name, bpDU* arg=0, int aspect = -1)
{
wizuiNotifier* notifier = ::wizNtrKit.getNotifier (nn_name);
notifier->notify (arg, aspect);
}
and this not inside a class. This is inside a header file!
I guess the call to a static function should be done only in the particular TU where it is defined.
Since my function is in a header file and if i make it static, will it be the case that where ever I include that header file the static function can used used in that translation unit?
The non-static inline function declaration refers to the same function in every translation unit (source file) that uses it.
The One Definition Rule requires that the body of the function definition is identical in every TU that contains it, with a longish definition of "identical". This is usually satisfied provided that the source files all use the same header, and provided that the function doesn't use any global names with internal linkage (including static functions) or any macros that are defined differently in different TUs.
I don't remember encountering that particular linker error before, but it's at least possible that one of these restrictions is responsible. It's your responsibility to satisfy the requirements: undefined behavior with no diagnostic required if you don't.
The static inline function declaration refers to a different function in each translation unit, that just so happens to have the same name. It can use static global names or macros that are different in different TUs, in which case the function might behave differently in the different TUs, even though its definition in the header file "looks the same".
Because of this difference, if the function contains any static local variables then it behaves differently according to whether it is static or not. If it is static then each TU has its own version of the function and hence its own copy of the static local variables. If it's inline only, then there is only one copy of the static local variables used by all TUs.
I am trying to create bunch of void methods and call them later in program.
I will demonstrate the code ahead to help better understand my issue.
.h file
static float sfloat;
namespace someNamespace
{
static void foo();
}
.cpp file
void someNamespace::foo(){cout<<sfloat<<endl}
above code is simpler version of class that I was working on.
I initialize sfloat in other .cpp file
otherFile.cpp
void initializeAndUseFoo(){sfloat = 5; someNamespace::foo();}
As far as my understanding goes, I expect foo to print out 5 but it prints out 0 instead.
This behavior occurs across all other static variables that I have as well(pointer included). It seemed that somehow the variables inside the function are never initialized as the value I assign.
However if I call out "sfloat" not through the function then I can call it out properly.(if I just print it out on console with just
cout<<"just print it not through the function : " <<sfloat<<endl;
then it is indeed 5
Thank you for reading.
A global static variable is static within one compilation unit. If you make another compilation unit, it will have a separate copy of that static variable.
This SO question explains what a compilation unit is in C++.
Since your variable is static and global in the same time, there will be a single instance of it in it's compilation unit. If you want to access that exact variable from another file, you will have to use the extern keyword. Without it, a new copy of that variable will be created in each compilation unit. You can find some information here, for example.
That's not a class, it's a namespace. static inside the namespace or at global scope gives methods and variables internal linkage. That means a copy of each will be available for each translation unit.
Because you modify (not initialize) sfloat in otherFile.cpp, only that version of the variable is modified. The original, initialized in .cpp file, retains the same value (which is the version printed by someNamespace::foo().