Что такое статический блок в C или C++?

Я хочу знать, что статический блок в C или C++ с примером? Я знаю, что такое статика, но в чем разница между статическим и статическим блоком?

5 ответов


Другой альтернативой является то, что вы можете искать аналогию статического блок в Java. Блок кода, который запускается при загрузке приложения. В C++ нет такой вещи, но ее можно подделать с помощью конструктора a статический объект.

foo.cpp:

struct StaticBlock {
    StaticBlock(){
        cout << "hello" << endl;
    }
}


static StaticBlock staticBlock;

void main(int, char * args[]){

}

однако. Я был укушен этим раньше, так как это тонкий крайний случай C++ норматив. Если статический объект недоступен никаким кодом, вызываемым main, конструктор статического объекта может быть или не быть называемый.

Я обнаружил, что с GCC hello получит вывод, а с visual studio он будет не.


нашел этой ответ на проект кода. Это связано с наличием дополнительной статической переменной, но я считаю, что она более надежна, чем ответ брэдгонсерфинга. В принципе, это так:

class Foo
{
public:
    static int __st_init;
private:
    static int static_init(){
        /* do whatever is needed at static init time */
        return 42;
    }
};
int Foo::__st_init = Foo::static_init();

это также означает, что, как и статические блоки Java, вам не требуется когда-либо иметь экземпляр class Foo, что полезно, когда класс может принимать много данных, и вам просто нужно автоматически вызвать что-то перед загрузкой, а не создавать дополнительный экземпляр пример этого. Вы можете проверить этот точный блок кода. Я просто скомпилировал его (с небольшим выходом из static_init () и имел main () print Foo::__st_init, просто чтобы убедиться), и он работал просто отлично.

$g++ -v

Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6.1/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.1-9ubuntu3' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++,go --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3)

EDIT:

Извините, что так поздно, но я проверил, что bradgonesurfing отметил:

если вы проверите его мой доступ к переменной в main " просто чтобы убедиться" вы гарантируете, что переменная достижима и таким образом переменная будет быть инициализирован и поэтому static_init будет называться. Ты уверен? выполняется, если вы не печатаете Foo::__st_init

я использовал следующее внутри main.cpp:

#include <iostream>

using namespace std;

class Foo
{
public:
    static int __st_init;
private:
    static int static_init(){
        /* do whatever is needed at static init time */
        cout << "Hello, World!";
        return 42;
    }
};
int Foo::__st_init = Foo::static_init();

int main(int argc, char** argv)
{
        return 0;
}

я составил с g++ ./main.cpp -o main и запустил его и получил дружеское " Привет, Мир!"сообщение на моей консоли. Просто чтобы быть тщательным, я также скомпилировал ту же версию, но без печати и скомпилировал с g++ ./main.cpp -g -o main. Затем я запустил исполняемый файл с gdb и имел следующее результат:

(gdb) break Foo::static_init
Breakpoint 1 at 0x400740: file ./main.cpp, line 12.
(gdb) start
Temporary breakpoint 2 at 0x4006d8: file ./main.cpp, line 19.
Starting program: /home/caleb/Development/test/main-c++ 

Breakpoint 1, Foo::static_init () at ./main.cpp:12
12              return 42;
(gdb) 

вот более текущая версия вывода для g++:g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2


в C/C++нет понятия с именем "статический блок". Java имеет это, однако, "статический блок" является блоком кода инициализатора для класса, который выполняется ровно один раз, прежде чем будет создан первый экземпляр класса. Базовая концепция "материал, который работает ровно один раз" может моделироваться в C/C++ со статической переменной, например:

int some_function(int a, int b)
{
 static bool once=true; 
 if (once)
 {
  // this code path runs only once in the program's lifetime 
  once=false; 
 } 
 ...
}

это не потокобезопасно, однако. Получение этой работы прямо в присутствии нескольких потоков может быть сложным и сложным иногда.


хотя действительно, C++ не имеет статических блоков как часть языка, вы can реализовать статические блоки без вас (как пользователя), используя любые классы или пространства имен, и может написать:

#include "static_block.h" 

static_block {
     int x = 1;
     int y = 2;
     int z = x+y;
     std::cout << z << " = " << x " << " + " << y << "\n";
}

или что еще вы хотите. Однако вы не можете иметь их в классах, только в области файла. См. подробное описание этого в my ответ к связанному вопросу и коду для static_block.h здесь.

Примечание: это не требует C++11 и будет хорошо работать со старыми компиляторами.


в C++ существует понятие анонимного пространства имен.

foo.cpp:

namespace {
    int x;
    int y;
}

чтобы получить тот же эффект в C

foo.cpp:

static int x;
static int y;

в простых выражениях компилятор не экспортирует символы из единицы перевода, если они объявлены статическими или в анонимном пространстве имен.