1

Say you have a certain class in which each instance of it needs to access the exact same set of data. It is more efficient to declare the data outside the class rather than have each instance make its own one, but doesn't this breach the 'no globals' rule?

Example code:

Foo.h

class Foo{
    Foo();
    void someFunction();
};

Foo.cpp

#include "Foo.h"

//surely ok since it's only global to the class's .cpp?
const int g_data[length] = {
//contains some data
};

Foo::someFunction(){
//do something involving g_data ..
}

..rather than making 'g_data' a member variable. Or is there some other way which avoids creating a global?

Robomoo
  • 57
  • 1
  • 5

5 Answers5

3

Use the modifier static which modifies the declaration of a class member so that is shared among all class instances. An example:

class A {
 int length = 10;
 static int g_data[length]; //Inside the class
}

And then you can access it like this:

int main(void) {
 std::cout << "For example: " << A::g_data[2] << std::endl;
}

You can find more on this matter here

Community
  • 1
  • 1
KiaMorot
  • 1,668
  • 11
  • 22
2

That's what a static member is for.

Thus you will have in your declaration :

class Foo{
    Foo();
    void someFunction();
    static int const sharedData[length];
};

And somewhere in your cpp file :

int const Foo::sharedData[length] = { /* Your data */ };
Quentin
  • 62,093
  • 7
  • 131
  • 191
1

Summarily, yes - your "global" is probably ok (though it'd be better in an anonymous namespace, and there are a few considerations).

Details: lots of answers recommending a static class member, and that is often a good way to go, but do keep in mind that:

  • a static class member must be listed in the class definition, so in your case it'll be in Foo.h, and any client code that includes that header is likely to want to recompile if you edit the static member in any way even if it's private and of no possible direct relevance to them (this is most important for classes in low-level libraries with diverse client code - enterprise libraries and those shared across the internet and used by large client apps)

  • with a static class member, code in the header has the option of using it (in which case a recompile will be necessary and appropriate if the static member changes)

  • if you put the data in the .cpp file, it's best in an anonymous namespace so it doesn't have external linkage (no other objects see it or can link to it), though you have no way to encapsulate it to protect it from access by other functions later in the .cpp's translation unit (whereas a non-public static class member has such protection)

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Agreed. Anonymous namespaces are a great way of keeping .h files clean - which is good not only for compile times, but also for developers reading your .h file as documentation of your API. – Allison Lock Nov 27 '14 at 15:23
0

What you really want is data belonging to the type, not to an instance of that type. Fortunately, in C++ there is an instrument doing exactly that — static class members.

Community
  • 1
  • 1
grzkv
  • 2,599
  • 3
  • 26
  • 37
0

If you want to avoid the global and have a more object-oriented solution, take a look at the Flyweight pattern. The Boost Flyweight library has some helper infrastructure and provides a decent explanation of the concept.

Since you are talking about efficiency, it may or not be a good idea to use such an approach, depending on your actual goal. Flyweights are more about saving memory and introduce an additional layer of indirection which may impact runtime performance. The externally stored state may impact compiler optimizations, especially inlining and reduce data locality which prevents efficient caching. On the other hand, some operations which like assignment or copying can be considerably faster because there is only the pointer to the shared state that needs to be copied (plus the non-shared state, but this has to be copied anyway). As always when it comes to efficiency / performance, make sure you measure your code to compare what suits your requirements.

Jens
  • 9,058
  • 2
  • 26
  • 43