Archduke
Archduke

Reputation: 349

Can you stop unused static objects from being constructed?

When I link a file that contains a static object, that object's constructor is ran regardless of whether the object is ever used or the header is even included. Is there a way in g++ to stop this behavior from occurring, or is the only answer to just not link the file?

foo.h

#include <iostream>

class Bar {
public:
    Bar(int inMemberInt) {
        std::cout << "In Bar constructor." << std::endl;
    }
};

class Foo {
public:
    static const Bar constVar;
};

foo.cpp

#include "foo.h"

const Bar Foo::constVar(1);

main.cpp

#include <iostream>

int main() {
    std::cout << "Hello." << std::endl; 

    return 1;
}

Build command

g++ foo.h foo.cpp main.cpp -o main

Output

In Bar constructor.
Hello.

Upvotes: 0

Views: 139

Answers (2)

Maxim Egorushkin
Maxim Egorushkin

Reputation: 136485

Another option is to a define static object in its own source file. Then compile that source file into an object file and link that into a static library (.a) along with other object files (if any). When linking your executable (or shared library) against a static library the linker includes only those .o files from the static library that resolve any of unresolved symbols. So that if nothing refers to that static object the object file where it is defined isn't linked into your executable or shared library.

Upvotes: 1

walnut
walnut

Reputation: 22152

You can make the class a template (probably with defaulted template parameter) and then the static data member's definition will be instantiated only when (odr-)used somewhere in the program.

This requires you to move the definition of the class members into the header, though. If this is too large of an impact, you might want to consider putting the static member in a base class that is a class template, which will have the same effect as making the whole class a template as long as you don't reference the static member anywhere. The static member's definition will need to be moved to the header in any case (explicit instantiation would counter the intended effect.)

This doesn't mean though that, if the static member is (odr-)used, the initializer will run only when the variable is used the first time in the program run. Whether that is the case or not is implementation-defined.


The alternative that guarantees not only that the initializer is never run when the variable isn't used in the program code, but also guarantees that it is run exactly when it is used the first time, is to use a local static variable in a static member function instead:

static const Bar& constVar() {
    static const Bar instance(1);
    return instance;
};

Then use it as constVar() instead of constVar. (The definition of the function can also be out-of-class.) This does however come with a performance penalty, because the implementation of local statics must be thread-safe.

Upvotes: 5

Related Questions