When should I write the keyword 'static' before a non-member function?
static
, as I think you're using it, is a means of symbol hiding. Functions declared static
are not given global visibility (a Unix-like nm
will show these as 't' rather than 'T'). These functions cannot be called from other translation units.
For C++, static
in this sense has been replaced, more or less, by the anonymous namespace, e.g.,
static int x = 0;
is pretty equivalent to
namespace {
int x = 0;
}
Note that the anonymous namespace is unique for every compilation unit.
Unlike static
, the anonymous namespace also works for classes. You can say something like
namespace {
class Foo{};
}
and reuse that class name for unrelated classes in other translation units. I think this goes to your point 3.
The compiler actually gives each of the symbols you define this way a unique name (I think it includes the compilation time). These symbols are never available to another translation unit and will never collide with a symbol from another translation unit.
Note that all non-member functions declared to be inline
are also by default static
. That's the most common (and implicit) use of static
. As to point 2, defining a static
but not inline
function in a header is a pretty corner case: it's not dangerous per se but it's so rarely useful it might be confusing. Such a function might or might not be emitted in every translation unit. A compiler might generate warnings if you never actually call the function in some TUs. And if that static function has within it a static variable, you get a separate variable per translation unit even with one definition in a single .h
which might be confusing. There just aren't many (non-inline) use cases.
As to point 4, I suspect those people are conflating the static member function meaning of static
with that of the linkage meaning of static
. Which is as good a reason as any for using the anonymous namespace for the latter.
The static keyword and its various uses in C++
Variables:
static
variables exist for the "lifetime" of the translation unit that it's defined in, and:
- If it's in a namespace scope (i.e. outside of functions and classes), then it can't be accessed from any other translation unit. This is known as "internal linkage" or "static storage duration". (Don't do this in headers except for
constexpr
. Anything else, and you end up with a separate variable in each translation unit, which is crazy confusing) - If it's a variable in a function, it can't be accessed from outside of the function, just like any other local variable. (this is the local they mentioned)
- class members have no restricted scope due to
static
, but can be addressed from the class as well as an instance (likestd::string::npos
). [Note: you can declare static members in a class, but they should usually still be defined in a translation unit (cpp file), and as such, there's only one per class]
locations as code:
static std::string namespaceScope = "Hello";
void foo() {
static std::string functionScope= "World";
}
struct A {
static std::string classScope = "!";
};
Before any function in a translation unit is executed (possibly after main
began execution), the variables with static storage duration (namespace scope) in that translation unit will be "constant initialized" (to constexpr
where possible, or zero otherwise), and then non-locals are "dynamically initialized" properly in the order they are defined in the translation unit (for things like std::string="HI";
that aren't constexpr
). Finally, function-local statics will be initialized the first time execution "reaches" the line where they are declared. All static
variables all destroyed in the reverse order of initialization.
The easiest way to get all this right is to make all static variables that are not constexpr
initialized into function static locals, which makes sure all of your statics/globals are initialized properly when you try to use them no matter what, thus preventing the static initialization order fiasco.
T& get_global() {
static T global = initial_value();
return global;
}
Be careful, because when the spec says namespace-scope variables have "static storage duration" by default, they mean the "lifetime of the translation unit" bit, but that does not mean it can't be accessed outside of the file.
Functions
Significantly more straightforward, static
is often used as a class member function, and only very rarely used for a free-standing function.
A static member function differs from a regular member function in that it can be called without an instance of a class, and since it has no instance, it cannot access non-static members of the class. Static variables are useful when you want to have a function for a class that definitely absolutely does not refer to any instance members, or for managing static
member variables.
struct A {
A() {++A_count;}
A(const A&) {++A_count;}
A(A&&) {++A_count;}
~A() {--A_count;}
static int get_count() {return A_count;}
private:
static int A_count;
}
int main() {
A var;
int c0 = var.get_count(); //some compilers give a warning, but it's ok.
int c1 = A::get_count(); //normal way
}
A static
free-function means that the function will not be referred to by any other translation unit, and thus the linker can ignore it entirely. This has a small number of purposes:
- Can be used in a cpp file to guarantee that the function is never used from any other file.
- Can be put in a header and every file will have it's own copy of the function. Not useful, since inline does pretty much the same thing.
- Speeds up link time by reducing work
- Can put a function with the same name in each translation unit, and they can all do different things. For instance, you could put a
static void log(const char*) {}
in each cpp file, and they could each all log in a different way.
the position of the *static* keyword in member method declaration
There is no difference. static
on the function declaration applies to the function.
An this
pointer will not be implicitly passed to this function, So you cannot access non static class members inside this function without explicitly passing the object to it.
To remove the static
first you should know and understand the purpose that it is designed this way. Without taking that in to consideration you are just bound to create a code smell of vast proportions.
Why can static member function definitions not have the keyword 'static'?
There's ambiguity alright. The same definition need not be for a member function at all.
Consider this:
namespace foo {
static void bar();
}
static void foo::bar() {
}
foo::bar
is required to be defined with the same linkage specifier.
For member functions, however, static
is not a linkage specifier. If it was allowed, the correctness of the definition of foo::bar
will be very very context dependent on what foo
is. Disallowing static
in fact eases the burden on the compiler.
Extending it to members in general, as opposed to just member functions, is a matter of consistency.
c++ static non class objects
Static functions are only visible in the specific source file, while as foo2()
could be visible in other files, too. If the declaration gets provided, through a header file, for example, you can call the non-static funtion from somewhere else
Why don't we have to declare static functions the same way we need to declare static variables in c++?
Static member functions are ordinary functions at the assembly level. The difference is only the hidden pointer 'this' that does not exist in them. They are basically global functions that exist like any other non static or non member (and not inline) function within the C++scope of a class name. Function scopes are C++ thing, they are not there at the CPU level.
Static variables are different. They exist before any class object is created. They are not created when a class instance is created. They are there as globals.
Perhaps it's done the way it's done to emphasize that difference.
Related Topics
Xxxxxx.Exe Is Not a Valid Win32 Application
Checking Value Exist in a Std::Map - C++
Defining a Variable in the Condition Part of an If-Statement
How to Throttle the Bandwidth of a Socket Connection in C
Random Number Generator That Produces a Power-Law Distribution
Detecting Usb Insertion/Removal Events in Windows Using C++
Visual Studio: Run C++ Project Post-Build Event Even If Project Is Up-To-Date
Assertion Failed (Size.Width>0 && Size.Height>0)
Lcov/Gcov Branch Coverage with C++ Producing Branches All Over the Place
How to Get the Window Handle of the Desktop
What Is an Iterator in General
Sizeof Class with Int , Function, Virtual Function in C++
Will a "Variablename;" C++ Statement Be a No-Op at All Times
Why Was the Space Character Not Chosen for C++14 Digit Separators
Round Double to 3 Points Decimal
Converting Yuv into Bgr or Rgb in Opencv