Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.71/7: Рейтинг темы: голосов - 7, средняя оценка - 4.71
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351

Ключевое слово static (использование для объявления переменной в классе)

05.07.2019, 12:17. Показов 1599. Ответов 27
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.
Почитал книжки и интернет, но не совсем понял:
Вот пример:
test.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#ifndef TEST_H
#define TEST_H
 
#include <iostream>
#include <memory>
 
class ITest
{
public:
    virtual int testID() = 0;
};
 
class CTest : public ITest
{
public:
    explicit CTest(int id = 0);
    virtual ~CTest();
    static ITest * test;
    virtual int testID();
private:
    int m_testID = 0;
};
 
ITest * getTestInterface(int id);
void stopTest();
 
#endif // TEST_H
test.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "test.h"
 
ITest * CTest::test = nullptr;
 
ITest *getTestInterface(int id)
{
    if(!CTest::test) {
        new CTest(id);
    }
    return CTest::test;
}
 
void stopTest()
{
    if(CTest::test) {
        delete CTest::test;
        CTest::test = nullptr;
    }
}
 
CTest::CTest(int id)
    : m_testID(id)
{
    test = this;
}
 
CTest::~CTest()
{
    std::cout << __PRETTY_FUNCTION__ << std::endl;
}
 
int CTest::testID() {
    return  m_testID++;
}
main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <iostream>
#include <cstring>
#include <fstream>
#include <thread>
#include <unistd.h>
 
#include "test.h"
 
void func(int id)
{
    ITest * ptr = getTestInterface(id);
    int idTest = ptr->testID();
    std::cerr << "ID( " << id << "): " << idTest << std::endl;
}
 
int main()
{
    std::thread func_thread1(func, 10);
    sleep(1);
    std::thread func_thread2(func, 15);
 
    func_thread1.join();
    func_thread2.join();
 
    sleep(3);
    stopTest();
    return 0;
}
Если вот так вызвать всё это, то переменная static ITest * test; будет проинициализирована 1 раз и в каждом вызове функции void func(int id) у нас будет использоваться один и тот же объект? И хоть из 50 потоков будет вызвана функция getTestInterface() все равно будет один и тот же экземпляр?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
05.07.2019, 12:17
Ответы с готовыми решениями:

Ключевое слово static для переменных в файле
Много где пишут, если в файле объявить переменную с классом памяти static, то такая переменная будет видна только в том файле где она...

Ключевое слово static
Здорова господа!!! Есть две функции f1() и f2(). #include &lt;iostream&gt; using std::cout; using std::endl; int&amp; f1() ...

Зачем использовать ключевое слово static?
Здравствуйте. Зачем использовать ключевое слово static? И в каких ситуациях нужно использовать именно static?

27
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:21
Цитата Сообщение от qwe123qwea Посмотреть сообщение
у нас будет использоваться один и тот же объект?
Да, только:
1) объект у вас в функции
C++
1
2
3
4
5
6
7
ITest *getTestInterface(int id)
{
    if(!CTest::test) {
        new CTest(id);
    }
    return CTest::test;
}
в это статическое поле так и не записывается
2) у вас гонка данных в коде
0
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351
05.07.2019, 12:26  [ТС]
Undisputed, а если
C++
1
2
3
if(!CTest::test) {
     new CTest(id);
}
поместить в мьютес?
В смысле не записывается?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:30
Цитата Сообщение от qwe123qwea Посмотреть сообщение
поместить в мьютес?
можно, но не нужно
лучше перед созданием потоков создать экземпляр и записать адрес в статическое поле
потому что операция записи в поле происходит 1 раз, а остальные доступы только на чтение
таким образом не будет мьютексов и не будет гонки данных
Цитата Сообщение от qwe123qwea Посмотреть сообщение
В смысле не записывается?
В прямом.
Цитата Сообщение от qwe123qwea Посмотреть сообщение
new CTest(id);
указатель который возвращат new вы разве куда-то записываете?
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
05.07.2019, 12:30
Цитата Сообщение от qwe123qwea Посмотреть сообщение
переменная static ITest * test; будет проинициализирована 1 раз
Верно.
Цитата Сообщение от qwe123qwea Посмотреть сообщение
в каждом вызове функции void func(int id) у нас будет использоваться один и тот же объект
Верно.
Цитата Сообщение от qwe123qwea Посмотреть сообщение
И хоть из 50 потоков будет вызвана функция getTestInterface() все равно будет один и тот же экземпляр?
Если вызов будет происходить после первой инициализации.
А так она не потоко-безопасна.
C++
1
2
3
if(!CTest::test) {
    new CTest(id);
}
Здесь может случиться так, что несколько потоков могут выполнить оператор new и создать утечку памяти.
Ну и да вероятно вы хотели написать так:
C++
1
2
3
if(!CTest::test) {
    test = new CTest(id);
}
0
 Аватар для eva2326
1673 / 501 / 107
Регистрация: 17.05.2015
Сообщений: 1,518
05.07.2019, 12:32
Цитата Сообщение от qwe123qwea Посмотреть сообщение
В смысле не записывается?
в прямом:

if(!CTest::test) {
CTest::test = new CTest(id);
}
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:34
Цитата Сообщение от Azazel-San Посмотреть сообщение
что несколько потоков могут выполнить оператор new и создать утечку памяти.
утечка памяти пол проблемы, там UB
может возникнуть ситуация когда два потока будут общаться с разными экземплярами
а такое поведение вообще не предполагается
1
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351
05.07.2019, 12:35  [ТС]
Azazel-San, eva2326, Undisputed, при отладке и при работе объект CTest::test нормально инициализируется, можете сами проверить.
Миниатюры
Ключевое слово static (использование для объявления переменной в классе)  
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:38
qwe123qwea,
loading
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
05.07.2019, 12:39
Цитата Сообщение от Undisputed Посмотреть сообщение
может возникнуть ситуация когда два потока будут общаться с разными экземплярами
Я думал ТС просто забыл добавить запись в статик поле ))
Цитата Сообщение от qwe123qwea Посмотреть сообщение
нормально инициализируется
А кто говорил об инициализации?
Вы же сами написали
Цитата Сообщение от qwe123qwea Посмотреть сообщение
переменная static ITest * test; будет проинициализирована 1 раз
, потом вы ее сами в nullptr инициализируете.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
05.07.2019, 12:40
Цитата Сообщение от Undisputed Посмотреть сообщение
указатель который возвращат new вы разве куда-то записываете?
Он в конструкторе присваивание делает.
3
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351
05.07.2019, 12:43  [ТС]
DrOffset, спалил, а я хотел поспорить ещё с ними, что это работает.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:44
DrOffset,
помоему я прежде такого не видел ))
Цитата Сообщение от qwe123qwea Посмотреть сообщение
при отладке и при работе объект CTest::test нормально инициализируется, можете сами проверить
какой то странный подход
но тем не менее, ваш код содержит UB и он не рабочий
1
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351
05.07.2019, 12:45  [ТС]
Цитата Сообщение от Undisputed Посмотреть сообщение
но тем не менее, ваш код содержит UB и он не рабочий
Вот это я и хотел выяснить, спасибо.
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
05.07.2019, 12:46
Цитата Сообщение от DrOffset Посмотреть сообщение
Он в конструкторе присваивание делает.
И вправду, интересно, однако.
Цитата Сообщение от Undisputed Посмотреть сообщение
ваш код содержит UB и он не рабочий
Где там тогда UB?
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
05.07.2019, 12:47
Цитата Сообщение от qwe123qwea Посмотреть сообщение
спалил, а я хотел поспорить ещё с ними, что это работает.
Так-то он прав в существу. Лучше это делать в фабричной функции, чем в конструкторе. Хотя бы потому, что любое случайное создание объекта вне вашей инфраструктуры поломает весь код, т.к. указатель перезапишется.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:47
Цитата Сообщение от Azazel-San Посмотреть сообщение
Где там тогда UB?
UB как минимум потому что есть вероятность параллельного доступа на модификацию данных без использования каких либо средств синхронизации
0
Mental handicap
 Аватар для Azazel-San
1246 / 624 / 171
Регистрация: 24.11.2015
Сообщений: 2,429
05.07.2019, 12:49
Цитата Сообщение от Undisputed Посмотреть сообщение
UB как минимум потому что есть вероятность параллельного доступа на модификацию данных без использования каких либо средств синхронизации
Ты о том что я писал по поводу new?
Так это не UB.
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
05.07.2019, 12:49
Цитата Сообщение от Azazel-San Посмотреть сообщение
Ты о том что я писал по поводу new?
нет)) ты вроде писал про утечку памяти
а я про гонку данных
это же разные проблемы
0
75 / 59 / 31
Регистрация: 20.03.2017
Сообщений: 351
05.07.2019, 12:49  [ТС]
DrOffset, это чисто пример, а там где используется не получится никак кроме через фабричную функцию создать объект.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
05.07.2019, 12:49
Помогаю со студенческими работами здесь

Ключевое слово static в объявлении функции
Доброго времени суток. У меня возник вопрос по поводу использования слово static в объявлении функции. На сколько мне известно данное...

Зачем и когда нужно писать ключевое слово static
Не как не могу понять зачем и когда нужно писать ключевое слово static. Может вы мне подскажите ?

Ключевое слово const после декларации функции в классе
Здравствуйте, у меня есть подобный класс-шаблон: template &lt;typename Type&gt; class Array { private: Type* ptr; // ...

Объявление static переменной в классе
class Worker { private : struct WorkerItem { UnicodeString fio; UnicodeString depart; UnicodeString exp; ...

Классы.Ключевое слово static - выдает ошибку "неразрешенный внешний символ"
Всем доброго времени суток. Изучаю С++ по Шпаку и по урокам на сайте cppstudio.com, предварительно хорошо ознакомившись с ассемблером... ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение Это мой обзор планшета X220 с точки зрения школьника. Недавно я решила попытаться уменьшить свой. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru