I have this problem with a static functions declared in a header file.
Say I have this file "test.cpp":
#include <cstdlib>
#include "funcs.hpp"
...do some operations...
void *ptr = my_malloc(size);
...do some operations...
The "funcs.hpp" file contains:
#include <ctime>
#include "../my_allocator.hpp" // my_malloc is defined here as a
// global static function
...some functions...
static int do_operation() {
// variables declaration
void *p = my_malloc(size);
// ...other operations
}
when I compile my program, I get an error 'my_malloc' was not declared in this scope, referred to the one used in the "funcs.hpp" file, while it doesn't complain with the one used in "test.cpp".
The function in question is defined as a global static function within the header "my_allocator.hpp", and all it does is to get an instance of the allocator object and use the malloc function:
static void * my_malloc(size_t size) {
return MYAllocator::instance()->malloc(size);
}
I'm not sure whether this problem is related to the scope of a function declared as static global inside a header, but what looks weird to me is that it complains in one case and not in the other: when I use it in a static function in a header (funcs.hpp) that includes the header where it is declared, it results in the error "not declared in this scope"; while it is OK when used from a file that includes the header "funcs.hpp".
Where am I getting wrong?
The static specifier specifies that the symbol (variable or function) will be visible only in this translation unit. I think thats not the case you want, so remove the static specifier.
Note what the compiler is saying: "my_malloc was not declared in this scope". Thats exactly what you specified with static: Internal linkage
Also note that this use of the static keyword was deprecated in favor of unnamed namespaces.
Related
I stumbled upon some C++11 code that looks like this:
// some_file.h
namespace blah {
class X {
public:
constexpr const static std::initializer_list<uint64> SOME_LIST =
{1,2,3};
};
}
// some_file.cpp
#include "some_file.h"
namespace blah {
constexpr const std::initializer_list<uint64> X::SOME_LIST;
}
Which compiles fine. I assume the definition in the cpp file is used to avoid symbol duplication in each file that includes the header (please correct me if I'm wrong).
I then tried the following:
// my_file.h
namespace bleh {
constexpr const static char SOME_CONSTANT[] = "yay";
}
// my_file.cpp
#include "my_file.h"
namespace bleh {
// if I add this or any other variation, compilation breaks!
//constexpr const static char SOME_CONSTANT[];
}
The code above does not work if I add an explicit definition in the .cpp file. So I am wondering: is there symbol duplication in the second case? If so, is there a way to define the variable without an enclosing class?
The static keywords mean two different things here:
When you declare a variable or function at file scope (global and/or namespace scope), the static keyword specifies that the variable or function has internal linkage. When you declare a variable, the variable has static duration and the compiler initializes it to 0 unless you specify another value.
When you declare a data member in a class declaration, the static keyword specifies that one copy of the member is shared by all instances of the class. A static data member must be defined at file scope. An integral data member that you declare as const static can have an initializer.
C++ needs you to define static class members somewhere, because the class symbol is global (and so is your member). This can't be done in the header because of multiple definitions.
In the second case every compilation unit uses its own variable and there is no global symbol.
Why static variable in a class has to be re-initialised as a global in the file?
Otherwise, it gives a linking error. What is the theory behind it? I understand that the static variable will be in the Data Segment.
my_class.h
class my_class
{
public:
static int m_fid;
void get_fid();
};
my_class.cpp:
#include <iostream>
using namespace std;
int main()
{
my_class t;
/**this gives a linking error */
my_class::m_fid = 0;
return 0;
}
First of all the definition of static variable is wrong.
Instead of my_class::m_fid = 0; you should define as int my_class::m_fid = 0; when you do that there will be no more linker error..
Another thing as per standard...
The definition for a static data member shall appear in a namespace
scope enclosing the member’s class definition.
Yes, static variables (wherever they are declared) go into the data segment.
static means different things depending where it's used, though.
At file or namespace scope, it means the variable is specific to the .cpp file (translation unit).
At local scope, it means the variable is specific to that scope, which may be specific to the translation unit, or shared between translation units if it's in an inline function.
At class scope, a static member declaration inside the class is effectively (almost) the same as one outside the class with the extern specifier.
Like a variable declared extern, a static member is only considered to be declared (and not defined) until a definition is reached.
There is an exception for some static const and static constexpr members, that they may be initialized inside the class and then immediately used, subject to the restriction that the address of the member is never used.
In C++ definition file (.cpp), sometimes I can define small functions to be invoked, for example:
// Class declaration
// Myclass.h
Class Myclass
{
...
void Classfunction();
...
}
// Class defination
// Myclass.cpp
#include "Myclass.h"
...
void helper_fun()
{
...
}
...
void Myclass::Classfunction()
{
...
helper_fun();
...
}
In the above example, we can see void helper_fun() is declared and defined in the .cpp file. The purpose of this function is to be invoked by the functions that have been defined in the class. Of course, the helper_fun can be declared in the head file first and then defined in the implementation file. My question is whether this is a good practice for C++ code writing. Moreover, does this practice have some bad effects? Thanks!
It would be good practice to have the helper_fun defined in an anonymous namespace within the source file.
Like this:
namespace {
void helper_fun()
{
//...
}
}
Reason being that if another helper_fun is defined in another source file with the same signature, you wouldn't have any risk with linkage errors. It's not to say that there will be, but rather, there could be one.
Also, you shouldn't put functions in your header if it's not going to be used outside of the respective source file.
Having local helper functions in the source files are very common. Normally they are either declared as static (e.g. static void helper_fun() { }) or in an anonymous namespace (e.g. namespace { void helper_fun() { } }).
Making the functions static or having them in an anonymous namespace is so that they wont be callable from the outside, and so that you can have more local functions with the same name.
If, however, you want to call the function from other source files, then define the function normally, and add a declaration in the header file.
If you need it to be public, and included in other files via the header file. Then put it there.
Otherwise there's no reason for it to be in the header.
If you declare helper_fun in the header, it becomes visible to users of Myclass.h. Do you want helper_fun to be used elsewhere?
By keeping it solely within Myclass.cpp you ensure it can only be used by code within Myclass.cpp.
Of course declare functions in .cpp files is ok. It is helper function, so, you shouldn't give its declaration to user. You can use anonymous namespace for internal linkage (by default functions has external linkage).
An unnamed namespace or a namespace declared directly or indirectly
within an unnamed namespace has internal linkage.
like this
namespace
{
// helper_fun has internal linkage.
void helper_fun()
{
}
}
I think I hvae a fundamental misunderstanding of namespace and/or static variable. But I have tried this test code (typed by hand, forgive typos)
test.h:
namespace test{
static int testNum=5;
void setNum(int value);
}
main.cpp:
#include <test.h>
int test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
when I run this I get the value 5, not 9 as I would have expected. It seems almost as if I have two instances of the testNum variable, but that seems to be the exact opposite of what static should be doing. I'm guessing I've made a mistake in assuming that these features were identical to their java equvilants somehow...
I also get an error stating that testNum is declared multuple times if I remove the static from my declaration of testNum, could someone explain why that is the case as well?
Thank you
First, your misunderstanding has nothing to do with namespaces, it's only about static. For the rest of this answer I'm going to refer to simply testNum because the fact it's in a namespace is irrelevant.
I'm also assuming you have another file, probably called test.cpp, which also includes test.h and defines the setNum function.
When a variable or function at namespace-scope (i.e. not a class member or local to a function) is declared static it means the entity's name is internal to that file. Formally it has "internal linkage", meaning it can't be referred to by name or linked to from other files (it can be indirectly referred to through a pointer or by passing it as an argument to another function.) That means if several files define static int testNum then each file has its own internal variable with that name, distinct from the testNum in every other file (in fact one file could have static int testnum and another could have static double testnum and another static char* testNum, they'd all be distinct and internal to each file.) If you put a definition like that in header then every file that includes the header has its own testNum.
So with static on your variable in a header you have a different variable called testNum in every file that includes test.h. That means if you set testNum in one file and call a function in a different file which uses testNum it refers to a different variable, which just happens to have the same name.
Because of this, declaring non-const static variables in headers is almost always wrong.
Without static you would have a definition of the testNum variable in every file that includes test.h, which is not allowed: every entity must be defined once and once only in your program. The way to solve that is to declare the variable in the header, but not define it, which you do by telling the compiler the variable is extern:
extern int testNum; // N.B. no "= 1" here
That tells the compiler there is a variable with "external linkage" called testNum, so when code refers to testNum it will always mean the same variable (not some name with internal linakge that is a different entity in every file.) After declaring an extern variable it is your responsibility to ensure there is exactly one definition provided somewhere in the program, so in exactly one file (i.e. not in a header that gets included in multiple files) you define it:
int testNum = 1;
static at namespace scope is a misnomer, and shouldn't be used. It
means simply that the entity declared static has internal name binding;
in other words, that the same name in other translation units will refer
to a different entity, and in the case of variable definitions, that
there will be a separate instance of the variable in each translation
unit. It has no effect on lifetime. (All variables declared or
defined at namespace scope have static lifetime.)
static at namespace scope is also deprecated. Don't use it.
With regards to declaring a variable in a header: prefix it with
extern, and not static. If a variable is declared extern, and
there is no initialization, the declaration is not a definition. Of
course, in this case, you must provide a definition somewhere (in a
single source file). Something along the lines of:
extern int testNum = 5;
int testNum = 5;
int testNum; // implicitly initialized with 0.
EDIT:
To clarify somewhat: there is some confusion here between lifetime and
name binding:
an object has a lifetime (auto, static or dynamic—or temporary, or exception), and
a name is bound to an entity; if the name is declared to be a variable, the entity is an object.
Do not confuse the keyword static with static lifetime. (Functions
can be static, but functions have no defined lifetime in C++; they're
just there.)
The rules regarding these are not very orthognal. Basically, with
regards to lifetime:
all variables declared at namespace scope have static lifetime, always,
variables declared at local scope have auto lifetime unless they are declared static, and
variables declared at class scope have the lifetime of the class object which contains them, unless they are declared static.
regards to lifetime.
Objects with static lifetime come into being sometime before main, and
live until after you return from main.
With regards to name binding:
variables declared at namespace scope have external name binding,
unless they are declared static, in which case they have internal
name binding (but this use of static is deprecated), or if they are
const, and are not declared extern,
variables declared at class scope have external name binding, even if they are declared static, and
variables declared at block scope have no binding.
Finally, there is the question of whether a declaration is a definition
or not. If it is a definition, memory is allocated and the object is
(or may be) initialized. If it is not a definition, it simply tells the
compiler that there is a definition somewhere else for the entity
(object) declared in the declaration. In general, a variable
declaration is a definition unless it is declared extern and does
not have an initializer.
You might want to make sure your code actually has problems before you post it asking what's wrong ;)
I copy/pasted and fixed your typos, and manually did the include:
#include <iostream>
using namespace std;
namespace test{
static int testNum=5;
void setNum(int value);
}
void test::setNum(int value){
testNum=value;
}
int main(){
test::setNum(9);
cout<<test::testNum;
}
result:
$ ./a.out
9
What you haven't said is what else is in your program. If you have more than just main.cpp, and include your test.h, then each .cpp file will have its own copy of testNum. If you want them to share then you need all but one to mark it as extern.
If you want to put function definitions in header files, it appears there are three different solutions:
mark the function as inline
mark the function as static
put the function in an anonymous namespace
(Until recently, I wasn't even aware of #1.) So what are the differences to these solutions, and when I should I prefer which? I'm in header-only world, so I really need the definitions in the header files.
The static and unnamed namespace versions end up being the same: each Translation Unit will contain it's own version of the function, and that means that given a static function f, the pointer &f will be different in each translation unit, and the program will contain N different versions of f (more code in the binary).
This is not the right approach to provide a function in a header, it will provide N different (exactly equal) functions. If the function contains static locals then there will be N different static local variables...
EDIT: To make this more explicit: if what you want is to provide the definition of a function in a header without breaking the One Definition Rule, the right approach is to make the function inline.
As far as I know, only inline and template functions can be defined in header files.
static functions are deprecated, and functions defined in an unnamed namespace should be used instead (see 7.3.1.1 p2). When you define a function in an unnamed namespace in a header, then every source code including that header (directly or indirectly) will have an unique definition (see 7.3.1.1 p1). Therefore, functions should not be defined in the unnamed namespace in header files (only in source files).
The standard referenced are from the c++03 standard.
EDIT:
Next example demonstrates why functions and variables shouldn't be defined into unnamed namespace in headers :
ops.hpp contains:
#ifndef OPS_HPP
#define OPS_HPP
namespace
{
int a;
}
#endif
dk1.hpp contains:
#ifndef DK1_HPP
#define DK1_HPP
void setValue();
void printValue();
#endif
dk1.cpp contains:
#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>
void setValue()
{
a=5;
}
void printValue()
{
std::cout<<a<<std::endl;
}
dk.cpp contains :
#include "dk1.hpp"
#include "ops.hpp"
#include <iostream>
int main()
{
// set and print a
setValue();
printValue();
// set and print it again
a = 22;
std::cout<<a<<std::endl;
// print it again
printValue();
}
Compile like this:
g++ -ansi -pedantic -Wall -Wextra dk.cpp dk1.cpp
and the output :
5
22
5
ops the variable a is different for the source file dk1.cpp and dk.cpp
static functions (equivalent to anonymous namespace) receive different copies for each TU. If the function is re-entrant this is basically identical (some compilers might have assembly-level differences) but if it isn't then it will have different static data for each TU. Inline functions are folded- that is, they have only one copy of static data for every TU.
You could consider wrapping the methods in a class instead of a namespace. Declare these methods as static and delete the constructor of the class to reinforce that this is not an object to be instantiated.
struct FooNamespace
{
FooNamespace() = delete;
static FooMethod1() {
...
}
static FooMethod2() {
...
}
};
You get the same general behavior as it belonging to a namespace with only a single implementation.