LINUX.ORG.RU

[C++] статические функции

 


0

0

Изучаю namespace'ы, столкнулся с вопросом. В чём разница между последующими вариантами внутри одного translation unit'a ?

1) static void func() { }

2) namespace { void func() { } }

3) namespace { static void func() { } }

Спасибо.

anonymous

1) Deprecated.
2) Именно так надо писать в соответствии со стандартом C++.
3) Масло маслянное

Deleted
()
Ответ на: комментарий от Deleted

> 1) Deprecated.

хто сказал?

> 2) Именно так надо писать в соответствии со стандартом C++.
> 3) Масло маслянное

$ cat test.cpp

namespace ns {

static void f1()
{
}

void f2()
{
    f1();
}

};

$ g++ -c test.cpp
$ readelf --all test.o | grep 2f
     5: 00000000     5 FUNC    LOCAL  DEFAULT    1 _ZN2ns2f1Ev
     9: 00000006    10 FUNC    GLOBAL DEFAULT    1 _ZN2ns2f2Ev

что называется "почувствуй разницу"

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от dilmah

>> > 1) Deprecated 
>> жжошь

В программах на C и старых программах на C++ ключевое слово static
используют (что приводит к путанице) для указания "использовать внутреннюю компановку" (п. Б.2.3). Не используйте static кроме как внутри функций (п. 7.1.2) и классов (п. 10.2.4).
    (c) Б. Страуструп, "Язык программирования C++"

Deleted
()
Ответ на: комментарий от Deleted

> В программах на C и старых программах на C++ ключевое слово static
используют (что приводит к путанице) для указания "использовать внутреннюю компановку" (п. Б.2.3). Не используйте static кроме как внутри функций (п. 7.1.2) и классов (п. 10.2.4).
(c) Б. Страуструп, "Язык программирования C++"

ну. и где здесь слово depricated и какая взаимосвязь между static и пространствами имён :-?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

>> namespace ns {

В исходном сообщении _анонимное_ пространство имён, так что s/ns //.

ivan@localhost ~ $ readelf --all test.o | grep 2f
     5: 0000000000000000     6 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_1L2f1Ev
     6: 0000000000000006    11 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_12f2Ev

Deleted
()
Ответ на: комментарий от klalafuda

>> ну. и где здесь слово depricated

Слова deprecated действительно нет, но в C++ для static предусмотрена другая роль - внутри функций и внутри классов. Возможность объявления статических функций вне классов с помощью static - это очтавлено только для совместимости с C и старыми версиями C++.

>> и какая взаимосвязь между static и пространствами имён :-?

Анонимные пространства имён какраз предназначены для замены static в таких случаях.

Deleted
()
Ответ на: комментарий от Deleted

> В исходном сообщении _анонимное_ пространство имён, так что s/ns //.

впрочем, да, если пространство имён именно анонимное оно автоматически объявляет определённые в нём ф-и как статические, факт.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от placement_new

> разве оно обьявляет его статическим? просто ты не сможешь ей воспользоваться не в пределеах единицы трансляции.

а разве это в конечном итоге не одно и то же?

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от placement_new

> в виду добавления уникального префикса.

на самом деле если посмотреть, что делает g++

ivan@localhost ~ $ readelf --all test.o | grep 2f
     5: 0000000000000000     6 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_1L2f1Ev
     6: 0000000000000006    11 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_12f2Ev

..то получается, что для статической ф-и он добавляет к имени L но
при этом независимо от в выходном ELFе объявляет обе ф-и как локальные.
впрочем, вполне возможно, что если бы на выходе был бы не ELF а формат,
которые не поддерживает указания видимости символов эта L решала бы.

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от placement_new

>> в связи с этим может какие нибудь еще расходы могут быть?

Какие имеются ввиду расходы? В данном контексте статичность означает только лишь то, что ты не сможешь использовать статическую функцию/переменную в другом модуле трансляции. И всё.

Deleted
()
Ответ на: комментарий от Deleted

>Слова deprecated действительно нет, но в C++ для static предусмотрена другая роль - внутри функций и внутри классов. Возможность объявления статических функций вне классов с помощью static - это очтавлено только для совместимости с C и старыми версиями C++.

Вы еще стандартность void main(void) { exit(0); } обсудите. Страниц так на пять-десять.

Absurd ★★★
()
Ответ на: комментарий от Absurd

>> Вы еще стандартность void main(void) { exit(0); } обсудите. Страниц так на пять-десять.

8)

Deleted
()
Ответ на: комментарий от klalafuda

у меня вот что получается:

$ cat test.cpp
namespace
{
  static void f1() { }

  void f2() { f1(); }
}

$ g++ -c test.cpp

$ readelf --all test.o

...

Таблица символов '.symtab' содержит 10 пунктов:
   Чис:    Знач   Разм Тип     Связ   Vis      Индекс имени
     5: 00000000     5 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_
     9: 00000006    10 FUNC    GLOBAL DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_

...

$ g++ --version | head -1
g++ (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)

--

т.е. функции f1() b f2() в анонимном namespace локальная и глобальная
 соответственно, но их имена задеманглены до того (и почему-то они одинаковые),
что как ни старайся, к ним не обратишься из другого tu.

anonymous
()
Ответ на: комментарий от klalafuda

s/задеманглены/заманглены/, конечно

anonymous
()
Ответ на: комментарий от anonymous

забавно. 

$ g++ --version
g++ (GCC) 4.1.1 20061011 (Red Hat 4.1.1-30)

так что разница лишь в минорной версии + сборка под fc6.
однако, если не референсить f1/f2 то они просто исключаются
из объектника, что в принципе понимаемо.

$ cat test.cpp
namespace
{

static void f1() {}

void f2() { f1(); }

};

void xxx() { f1(); f2(); }

$ g++ -c test.cpp
$ readelf --symbols test.o  | grep FUNC
     5: 00000000     5 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_
     6: 00000006    10 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_
    10: 00000010    15 FUNC    GLOBAL DEFAULT    1 _Z3xxxv

что несколько удивляет это то, что вроде бы практически один и
тот же g++ явно по-разному генерирует выходной объектник :-/

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от klalafuda

хм...

GCC 3.4.6:
     5: 0000000000000000     6 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_
     9: 0000000000000006    11 FUNC    GLOBAL DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_

GCC 4.2.4:
     5: 0000000000000000     6 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_
     6: 0000000000000006    11 FUNC    LOCAL  DEFAULT    1 _ZN37_GLOBAL__N_test.cpp_

GCC 4.3.1:
     5: 0000000000000000     6 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_1L2f1Ev
     6: 0000000000000006    11 FUNC    LOCAL  DEFAULT    1 _ZN12_GLOBAL__N_12f2Ev

Deleted
()
Ответ на: комментарий от Deleted


в общем где-то что-то поменялось в g++ причём при переходе между минорами 4.1.1->4.1.2. а поменялось на самом деле достаточно значительно, бо раньше был LOCAL - одно поведение при линковке, теперь стал GLOBAL - потенциально уже другое :-/

// wbr

klalafuda ★☆☆
()
Ответ на: комментарий от Deleted

> Слова deprecated действительно нет, но в C++ для static предусмотрена другая роль - внутри функций и внутри классов. Возможность объявления статических функций вне классов с помощью static - это очтавлено только для совместимости с C и старыми версиями C++.

Трава, голоса, странные фантазии.

anonymous
()
Ответ на: комментарий от klalafuda

>namespace ns {

ага, типа обманул всех. ns убери, и попробуй ещё раз

devinull ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.