Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: inline C++17  (Прочитано 10144 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« : 19-08-2020 12:22 » 

всем привет )

прошу у знатоков свежих стандартов C++ пояснить, баг это GDB или не баг, а так и должно быть.

Что делается: объявляется inline global_var в файле s_global_var.h.

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

Что получается: если класс переменной имеет имя (s_global_var) , то экземпляр, как и положено, всего один. Если имя s_global_var закомментировать, то экземпляра три!

В чём подвох? Улыбаюсь


онлайн компилятор с заряженным примером (такое же поймал и на своём GDB в составе QtCreator)
https://onlinegdb.com/H1QQ899Gw

сюда копирую, если вдруг ссылка пропадёт

s_global_var.h
Код: (C++)
#pragma once
#include <iostream>

struct s_parent_for_global_var
{
    s_parent_for_global_var()
    {
        std::cout<<"s_parent_for_global_var(), this=="<<(void*)this<<'\n';
    }
};

struct /*s_global_var*/:public s_parent_for_global_var
{
}inline global_var;

main.cpp
Код: (C++)
#include "global_var.h"

int main()
{
    return 0;
}

s_global_var.cpp
Код: (C++)
#include "global_var.h"

some.cpp
Код: (C++)
#include "global_var.h"
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 19-08-2020 21:23 » 

О боже, что они с С++ делают...
Это новшество C++17.

Попробуй писать меньше букв:
inline s_parent_for_global_var global_var;

То, что закомментировано — определение новой struct с наследованием.

Ты оставил :public снаружи. Анонимная структура? Опять таки, тут наследование.
Я бы, чтоб не есть свой и чужой мозг, сперва определил тип, а потом уже объявлял переменные.
« Последнее редактирование: 19-08-2020 21:28 от RXL » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Finch
Спокойный
Администратор

il
Online Online
Пол: Мужской
Пролетал мимо


« Ответ #2 : 20-08-2020 02:57 » 

Я честно говоря не совсем понял, для чего этот сахар. Но все примеры, которые я вчера видел, говорят о том, что, переменная должна быть константным типом.
Код: (C++)
inline s_parent_for_global_var const global_var;
Записан

Не будите спашяго дракона.
             Джаффар (Коша)
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #3 : 20-08-2020 04:20 » 

RXL, Finch, родительский класс отделён в примере именно для возможности сделать отладочный вывод (так как в безымянном типе конструктора нет)


Попробуй писать меньше букв:
inline s_parent_for_global_var global_var;

.... сперва определил тип, а потом уже объявлял переменные.

само собой, что так я и делаю, код выше - демонстрация странного глюка. Но там всё законно с точки зрения синтаксиса, в том то и дело Улыбаюсь

Finch, нет, const не обязателен. inline предписывает линкеру найти в глобальной области (точнее - в соответствующем неймспейсе) все одинаково определённые переменные или функции и на этапе линковки оставить только один экземпляр, при этом неважно, в скольких единицах трансляции произошло объявление (из-за включения инклуда)

Само собой понятно, что я не буду нарываться и определю имя, а переменную объявлю отдельно при помощи имени класса. Но вопрос из первого поста остаётся открытым
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 20-08-2020 09:11 » 

Это не глюк. Анонимная структура тоже имеет имя. Три анонимные структуры имеют разные имена.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #5 : 20-08-2020 09:23 » 

RXL, а, ну то есть логика такая - если я имя даю сам, то оно используется во всех случаях, а если имя автоматически выдаёт компилятор, то эти имена и получаются разные. Ну, это можно принять за объяснение
Записан

RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #6 : 20-08-2020 09:26 » 

Попробуй сперва сделать typedef struct :public .... somename, а потом уже определил переменную типа somename. Чую, будет взрыв компилятора.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Алексей++
глобальный и пушистый
Глобальный модератор

ru
Offline Offline
Сообщений: 13


« Ответ #7 : 20-08-2020 10:01 » new

RXL, хех, тут ещё одна хохма выплыла

typedef честно определяет новое имя, поэтому экземпляр один, как и ожидается
Код: (C++)
typedef struct :public s_parent_for_global_var
{
} s_global_var;

inline s_global_var global_var;
s_parent_for_global_var(), this==0x601192

а вот более рекомендуемый using, судя по всему, не вводит новое имя, а вводит чистый алиас. Экземпляры размножаются Отлично Нежданчик, однако

Код: (C++)
using s_global_var=struct :public s_parent_for_global_var
{
};

inline s_global_var global_var;
s_parent_for_global_var(), this==0x601192
s_parent_for_global_var(), this==0x601194
s_parent_for_global_var(), this==0x601196

Добавлено через 2 минуты и 14 секунд:
в общем, просто запоминаю для себя правило - для глобальных переменных всегда делать имя класса
« Последнее редактирование: 20-08-2020 10:03 от Алексей++ » Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines