I'm trying to port some C code over to C++ and an array declaration (or rather, a series of array declarations) is giving me problems. The code is organized like this: first, a global array is declared, like so:
static const Foo foos[100];
Then, a bunch of other arrays are declared and initialized, all of which reference certain elements of the foos array, like so:
static const Bar bar1[3] = { .... &foos[3]; .... }
Finally, the original array is re-declared and initialized. The elements of the array make references to the bunch of arrays we just declared (in other words, the structures are mutually recursive):
static const Foo foos[100] = { .... &bar1[1]; .... }
In C, this works fine. The first declaration just serves to say "hey, I'm going to need an array of 100 Foo's later on", and then the second declaration actually tells the compiler what data we'd like to populate the array with. Because the structures I'm dealing with are mutually recursive, this all works out really nicely.
However, C++ is giving me real problems with the re-declaration. I'm not really a C++ programmer, but I believe this all has something to do with C++'s rules on default initialization.
So here's my question: how can I capture the above model in C++? How can I pre-declare the type and size of an array without actually initializing the contents?
(Don't bother telling me this is bad design -- I'm actually working on a compiler that targets C, so it's irrelevant whether the design of the computer-generated C code is good or bad. I'd just like to know how to pre-declare arrays of structures in C++.)
It works in C because C has tentative definitions, which weren't carried over to C++. For example, this is perfectly legal C code, but illegal C++ code:
int a;
int a;
int a;
If you want to declare an array (or any other variable) without defining it, use extern:
extern const Foo foos[100]; // declaration
const Foo foos[100] = ...; // definition
You cannot combine extern with static, but you can put stuff into an anonymous namespace, which more or less has the same effect. Note that top-level variables are always static; the static modifier on a global variable means "limit the visibility of this variable to the current translation unit".
Instead of making it static, change the declaration of Foo to extern.
extern const Foo foos[];
static const Bar bar[] = { ..., &foos[13], ... };
const Foo foos[] = { ..., &bar[1], ... };
Related
I want to define a function that, when given an integer, will return a string. Like this:
# Pseudocode
function get_string(i)
return my_string_array[i]
end
The strings will be hard coded into the application. The function prototype is declared in a header file:
// header.h
const std::string &get_string(const int i);
The way I see it, I have two options for declaring the hard-coded strings.
Option #1: Declare a static variable in get_string
// source.cpp
const std::string &get_string(const int i)
{
static const std::string values[] = {
std::string("foo"),
std::string("bar"),
std::string("baz"),
};
// Assume bounds checking is performed on i.
return values[i];
}
Option #2: Declare global constant in an anonymous namespace
// source.cpp
namespace
{
const std::string values[] = {
std::string("foo"),
std::string("bar"),
std::string("baz"),
};
}
const std::string &get_string(const int i)
{
// Assume bounds checking is performed on i.
return values[i];
}
For this limited use-case, are these declarations functionally equivalent? Does the program treat static constants in functions differently from globally declared constants or constants declared in anonymous namespaces?
I'm aware of the obvious accessibility differences (i.e. constant declared in local namespace is available globally to all functions defined in the same translation unit), but that can be chalked up as an advantage either way depending on the scenario, so for the purposes of this question this difference can be omitted.
Strings defined as static array inside your get_string function will be constructed on the first get_string call, while strings in global namespace will be constructed on application start.
So the problems that might arrise are different for both aproaches. For example if you go with defining strings at global scope then you should not use it before your main is executed, otherwise you never know if they got constructed. If you go with static construction inside get_string you may encounter threading problems at least until c++11, after that magic statics should fix this for you.
Why dont you put them inside const char* global array?
[edit]
Global array is not the right way to do it, as I suggested above. Another thing for you to consider is to go with option 1, but instead of array of strings create array of const char* string literals. Array of std::string object's will duplicate your string literals. You would have to probably also return const char* - so maybe thats not what you want.
I've been learning C++, and I've come across static variable (I have prior knowledge from C89), and in the resource i'm using, they've declared a static variable in a class such as:
class nameHere
{
public:
static int totalNum;
}
int nameHere::totalNum = 0;
int main()
{}
For Example.
What I don't understand is that, since I've already declared that the static variable is an integer in the class definition, why do I need to also declare it as an integer outside of the class definition?
Would it not make sense to simply initialise it like so:
nameHere::totalNum = 0;
int main()
{}
Is there a particular reason or simply a convention of C++?
Thanks for all the help!
This would (probably) make the language even more difficult to parse (and it's already almost insanely difficult to parse anyway).
As it is, the datatype (int, long, my_class, whatever) tells the compiler that what it's seeing is the beginning of a declaration (which, in this case, is also a definition). Without that, the compiler would have a rather more difficult time sorting things out.
In the specific case of things at global scope, it wouldn't be that bad, because at global scope about all you can have is a series of declarations. At any other scope, however, things would be more difficult (and having one rule at global scope, and another elsewhere would be ugly indeed).
In C++11 you can simply initialize the variable inside the class:
class nameHere
{
public:
static const int totalNum = {0};
}
There is a difference between a definition and a declaration.
While the static variable in the class has been declared, it has not been defined. The One Definition Rule, explains declarations and definitions and states
In any translation unit, a template, type, function, or object can have no more than one definition. Some of these can have any number of declarations.
Therefore, the full type of the object must be used when declaring the variable.
Given the following header file, if 'a' is defined inside the main body, I get a warning "unused variable 'a'" and linker error "undefined reference to 'a'.
header.h:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
extern int* a;
void f()
{
std::cout<<*a <<std::endl;
return;
}
#endif
main.cpp:
#include "header.h"
int main()
{
int* a = new int(10);
f();
}
However, if 'a' is defined outside of main(), the program links with no errors and f() works as expected (prints 10). Why is this?
Example:
int* a = new int(10);
int main()
{
f();
}
int* a = new int(10);
for this line, if in the main function, you are defining a local variable.
so the extern int* a; only declare a variable, but not define it. then get a linkage error on that symbol
You need to learn about name binding, which determines how two
declarations of the same name are related. When you define a variable
within a function, its name has no linkage; i.e. the entity it refers to
is distinct from any other entity in the program.
More generally: a declaration (and in this sense, a definition is also a
declaration) associates a symbol with an entity—an object (in
which case, the declaration declares a variable), a function, a
reference, a type or anything else you can declare in C++. Whether
different declarations of the same name associate with the same entity
or not is defined by their linkage. C++ recognizes three
different types of linkage:
external linkage, in which the entity can be referred to by declarations in other transation units,
internal linkage, in which the entity can be referred to by other declarations in the same translation unit,
and no linkage, in which the entity cannot be referred to by any other declaration.
Variables declared at block scope (i.e. local variables) have no
linkage, unless they are explicitly declared extern (and a local
variable declared extern cannot be a definition). So the int a in
main declares (and defines) an entity which is independent of any
other a in the program. Variables declared in namespace scope have
external linkage, unless they are declared static, in which case they
have internal linkage; when you define int a at namespace scope, it
has external linkage, and so refers to the same entity you declared with
extern int a in the header.
When you define the variables inside main, it only has scope inside the main function.
The global extern cannot resolve to that. In other words the linker cannot match the extern declared globally to the variable definition inside the main function.
If you define a inside of main, then its scope (visibility) is restricted to main -- an extern declaration will not make it visible anywhere else.
You have to define it at namespace scope (i.e., outside any function) for it to be visible in other translation units.
It's rather annoying to read 4 answers explaining what's wrong, but none explaining how the correct way to fix it. It's probably a safe guess that if the OP doesn't know about scoping he probably also doesn't know about passing variables to a function.
The Problem
You're trying to get at the value of a variable, but the variable is in another function. How can I get at it? Well, the simple answer is, you don't WANT to get at it. You heard me right. The entire reason to use a function is reusability, if you tie your newly created function to another function then you can't use it everywhere. Remember, functions help you be lazy. And a good programmer is a lazy programmer. If you can write a function once and use it in a million places, you're doing it right. ;)
But I still really want to get at the value of that variable
Then you want to use a function parameter to pass the variable to the function.
Functions are named because you can think of them in terms of math. Put variables in, get out useful data after the function has run and done interesting things with those variables. So let's say you have a math function y = f(x), the equivalent of this would be int f(int x) { /*stuff here*/ } then you call it in your main function using int y = f(a) where a is some variable or number.
You want to avoid global variables because they don't always do what you expect (especially if you have a lot of code, it's very easy to accidentally use the same name.)
In your case you want the function to print out the contents of a specific variable, so I think perhaps you're seeking a way use that function with any specific variable. So here's how you do that.
void f(); //hi, I'm a function prototype
void f(int a); //hi, I'm a function prototype that takes a parameter
void f(int a, int b); //hi, I'm a function prototype that takes two parameters (both ints)
void f(int a, ...); //hi, I'm a function prototype that takes an int then any number of extra parameters (this is how printf works.)
So what you really want to do is change your code to something like:
header.h:
#ifndef HEADER_H
#define HEADER_H
#include <iostream>
// extern int* a; // We don't need this
void f(int* a)
{
if (a != NULL) //always, always check to make sure a pointer isn't null (segfaults aren't fun)
std::cout<<*a <<std::endl;
//return; //Don't really need this for a function declared void.
}
#endif
main.cpp:
#include "header.h"
int main()
{
int* a = new int(10);
f(a);
return 0; //main is declared as returning an int, so you should.
}
Functions by value, pointer and reference
So, in your examples I gave I used int rather than int* in your example. The difference between the two is the first one passes the parameter by value. The other by pointer. When you pass a variable to a function a copy of it is ALWAYS made. If you pass it a int, it makes a copy of the int, if you pass it a 4 MB structure it will make a copy of the 4MB structure, if you pass it a pointer to a 4MB structure is will make a copy of the pointer (not the entire structure.) This is important for two reasons:
Performance: Making a copy of a 4MB structure takes some time.
Ability to change contents: If you make a copy of the pointer, the original data is still in the same place and still accessible through the pointer.
What if you want 1 and not 2? Well then you can declare the pointer const. The prototype looks like this: int f(int const* a);
What if you want 2 and not 1? Tough cookies (there no good reason anyway.)
Finally, you can also declare a function to take a reference and not a pointer, the big difference between a reference and a pointer is a reference will not be NULL (and you can't use pointer arithmetic on a reference.) You will want to use either pass by reference or pass by value normally. Needing to pass by pointer is something that I almost never need to do, in my experience it's more of a special case sort of thing.
Pass by reference: int f(int& a);
Pass by const reference: int f(int const& a);
So to sum up:
if you have function that needs parameters:
then:
if you do not need to modify the contents:
then:
if the size of the variable is small:
pass by value: int f(int a);
else if the size of the variable is large:
then:
if the value of the address can be NULL:
pass by const pointer: int f(int const* a);
else:
pass by const reference: int f(int const& a);
else if you do need to modify the contents:
then:
if the value of the address can be NULL:
pass by pointer: int f(int* a);
else:
pass by reference: int f(int& a);
There's some more cases, but these are the main ones, see this website for more details.
When you define the variable in the function main it is valid only in the scope of main. You can define in all function a variable with the name a. But these would be different variables, because each has it's owen scope.
Technically the variable is allocated on the stack while the function is called, therefore each instance has its own storage.
I have a few questions about the static keyword in C++ (and probably with other languages as well.) What is the purpose of declaring a function as static?
void static foo(int aNumber) {
... }
How about a static inline function?
void static inline foo(int aNumber) {
... }
Is there any benefit to using the static keyword with a function, and do those benefits apply to class functions as well?
I realize some datatypes like structs and arrays have to be static when compiling with an older compiler, but is there any point when using a new ANSI-C++ compiler (like MS VC++ 2008)? I know that using a static variable inside a loop saves time by keeping the data in memory and not reallocating memory every loop iteration, but how about when a variable is declared only once, like at the top of a header file or within a namespace?
Depends on Context:
Like many things in C++, static means different things depending on its context.
It's very common in C++ for the same word to mean different things depending on its context.
For example:
* is used for multiplication, dereferencing a pointer, and creating pointers.
& is used to get the address of variables, to declare a reference, and as a bitwise AND operator.
Global use of static:
If you declare a function or variable as static outside of a class and in global scope, it is specific to only that file. If you try to use that variable or function in a different file (via a forward declaration) you will get a linking error.
Example:
a.cpp:
static void fn()
{
cout<<"hello a!"<<endl;
}
b.cpp:
void fn();
void gn()
{
fn();//causes linking error
}
This feature allows you to use a function that no other file will ever see, that way you don't cause possible linker errors of a symbol defined multiple times. The preferred method to do this is with anonymous namespaces though:
a.cpp:
namespace
{
void fn() // will be static to a.cpp
{
cout<<"hello a!"<<endl;
}
}
Inside of a class use of static:
If you declare a function or variable as static inside of a class (or struct), it is a class function or class variable. This means that there is only one for that whole class. A class function can only use class variables. A class variable is shared amongst all instances of that class.
class C
{
public:
static void fn()
{
y = 4;//<--- compiling error
// can't access member variable within a static function.
}
int y;
}
This is a great feature to use if you have something that is specific to the class of your objects, but not specific to an instance.
Inside a function use of static:
If you declare a variable as static inside of a function, you can consider that the variable value will persist upon calls. It will only be initialized once.
Example:
//Will print 0, then 1, then 2, ...
void persistentPrintX()
{
static int x = 0;
cout << x << endl;
x++;
}
I personally try to avoid this, and you probably should to. It is not good to have global state. It is better to have functions that given the same input guarantees the same output.
Just like in the English language:
The concept of context sensitive meaning is not specific to C++, you can even see it in the English language.
I am going to screen a movie (Means showing the movie)
The screen on the TV is broken (Means a part of the TV)
Other meanings in other programming languages:
Depending on the programming language there can be a different meaning, but the first thing most people think of when you say static is a class variable/function vs a member variable/function.
I hang around on the ##c++ irc channel on irc.freenode.net and I really like the clarification on static that the bot nolyc is programmed to give. I quote word for word:
When used inside a function, the
static keyword indicates that a
variable is shared between all calls
of the function. When used inside a
class, it indicates that the variable
or function is a member but is not
tied to a specific instance. When
used inside a namespace, it specifies
internal linkage.
I hope that clears things up. I haven't answered all your questions. I would say that you should use the static keyword to do what it was intended to do. Use it as a tool to accompolish your task, if it is the right one for the job. As far as benefits go, I wouldn't worry. If you need to optimize, then think about those effects if there is no other resort.
I hope this helps.
I can do this
extern int i;
extern int i;
But I can't do the same with a class
class A {
..
}
class A {
..
}
While in both cases no memory is being allocated.
The following are declarations:
extern int i;
class A;
And the next two are definitions:
int i;
class A { ... };
The rules are:
a definition is also a declaration.
you have to have 'seen' a declaration of an item before you can use it.
re-declaration is OK (must be identical).
re-definition is an error (the One Definition Rule).
The closest equivalent to extern int i with a class is a forward declaration, which you can do as many times as you like:
class A;
class A;
class A;
class A{};
When you define the actual class you are saying how much memory is required to construct an instance of it, as well as how that memory is laid out. That's not really the issue here, though.
The first (extern) makes a reference to an existing variable. So you are just indicating the variable twice.
The class declaration gives meaning to a type (your class: A). You are trying to give two meanings to A. This is not of any use for you, and can only confuse, so the compiler protects you from it.
Btw, if you put both classes in difference namespaces you can give them the same name.
You can declare a class and an object multiple times, what you can't do is define it more than once.
extern makes this a declaration and not a definition (because there is no initializer):
extern int a;
The body makes your class a definition and not just a declaration. You can define a class once.
you can do
class A;
as often as you want and then in one file define it with
class A { ... }
Example for this:
classB.h:
class A;
class B { A *a; }
classA.h:
class B;
class A { B *b; }
But in the first case ther is no contradiction.
extern int i;
extern double i;
won't work either.
So if you create class A to times it wouldn't be possible to decide who A is.
I guess the real question is 'why would you want to?'. The situation sometimes arises when you include a header file multiple times in the same translation unit (.cpp file). If this is the case, you should look at using include guards to keep the compiler happy.
Another reason that this might be causing problems for you is that you're using a 3rd-party library which defines classes whose names conflict with your own classes. In this case you should look at using namespaces to resolve the ambiguity.
In both cases 'extern int i;' is referencing the same object (declared elsewhere) and so the multiple declarations are unambiguous. If you wrote:
extern int i;
extern float i;
The compiler would complain about the ambiguity (because it wouldn't know which variable you intended to manipulate if you wrote 'i=0;'.
Duplicate class declarations gives rise to the possibility that declarations are different; again, how would the compiler know which one to use when it encounters 'A foo;'? I guess the compiler could compare the class declarations and verify that they're infact identical, but this would be an awful lot of effort to go to when the alternative solutions (namespaces, include guards, renaming) are so much easier (and probably less confusing for whoever ends up reading the code).
It has nothing to do with declarations vs definitions. The issue is types versus objects.
extern int i;
tells the program that at an object of type int exists, and its name is i. Because it is extern no storage is allocated for it here, but somewhere else, probably in another translation unit, it is defined and storage is allocated for it.
class A {
..
};
defines a type named A. It doesn't allocate any objects or variables. It makes absolutely no difference at runtime, and no storage is allocated for it, because it is not an object. It simply introduces a new type to the compiler. From this point on, you are able to create objects of type A, and they will have storage allocated for them.
I gave it some thought. I realized class in not a data type, it is a enabler for defining a data type.
So in
extern int i;
extern int i;
int is a data type. So we are re-declaring a variable not a data type.
But in
class A {...};
class A {...};
A is a data type. And we are re-defining a data type, which is not allowed, of course.