Здравствуйте, Sergey, Вы писали:
S>Инициализация массива внутри класса
S>Задача, необходимо иметь массив указателей на элементы класса. S>Пример решения:
S>[ccode] S>typedef struct { S> int a; S> int *p; S>}Tarray;
S>Какие ещё могут быть варианты? S>Какие недостатки решения?
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Здравствуйте, saf_e, Вы писали:
_>>К сожалению в С++ нет автоматических способов такое сделать.
EP>http://liveworkspace.org/code/3vNkxu$0 EP>
Я имел в виду, что при изменении layout'a класса, придется дописывать руками соотв. структуру.
Круто
Выглядит, не как С++ Т.е. теперь уже можно размазать код конструктора по объявлению класса...
В данном контексте я бы ожидал что выражение: &a будет соотв. int Foo::*, а не int *
R>А для чего в этом примере rvalue-ссылку использовать? Чем обычная хуже?
Это "не совсем" rvalue — это так называемая "universal reference" — она биндится ко всему — и к reference, и к rvalue.
Конкретно в этом примере без разницы, что auto, что auto&, что auto&&, что const auto&.
Здравствуйте, saf_e, Вы писали:
_>Я имел в виду, что при изменении layout'a класса, придется дописывать руками соотв. структуру.
А я не знаю что именно хочет получить ТС. Вообще этот массив держать per-object не обязательно — можно разрулить в compile-time.
_>Круто _>Выглядит, не как С++
Surprisingly, C++11 feels like a new language: The pieces just fit together better than they used to and I find a higher-level style of programming more natural than before and as efficient as ever.
R>А для чего в этом примере rvalue-ссылку использовать? Чем обычная хуже?
В данном случае тип "auto&&" как раз и разворачивается в "обычную" lvalue ссылку. Убедиться в этом можно, если на место auto подставить тип явно, мы получим ошибку компиляции:
Здравствуйте, Sergey, Вы писали:
S>Инициализация массива внутри класса
S>Задача, необходимо иметь массив указателей на элементы класса.
<>
Если нужны указатели на члены данного экземпляра, — то напрашивается очевидный вариант: std::vector.
Размещать массив где-то на стеке — это UB (элементарно же: по выходу из конструктора стек разрушается), а где-то в статическом хранилище — это на грани UB (несколько одновременно живущих объектов будут перезаписывать этот массив, что сломает логику, а при известном невезении — получим ещё и висячие указатели на члены разрушенного объекта).
Делать свой рукодельный массив — а оно надо? Возни много, за памятью следить...
Либо завести тип "массив" (а не указатель).
(здесь я не позаботился о копировании и присваивании — понятно же, что копировать/присваивать эти векторы нельзя, — надо оставлять их привязанными к родному объекту).
Если нужны указатели на члены класса, — это немножко другая история.
Напомню: указатель на член может быть связан с любым (другим) экземпляром — но только данного класса или его наследника.
class CTest;
typedef int CTest::* CTestIntField;
struct CTestFields
{
int n;
CTestIntField* a;
};
class CTest
{
public:
int y, z, x;
static CTestFields const& fields()
{
static const CTestIntField a[] = { &CTest::x, &CTest::y, &CTest::z };
static const CTestFields f = { ARRAY_SIZE(a), a };
return f;
}
};
int main()
{
CTestFields const& f = CTest::fields();
CTest p; p.x=1;
CTest q; q.x=4;
printf("%d %d", p.*f[0], q.*f[0]); // постфиксный оператор [] имеет приоритет перед инфиксным .* - скобки не нужны
}
Здравствуйте, Sergey, Вы писали:
S>Какие недостатки решения?
у неправильного решения нет недостатков
адреса нестатических локальных переменных функций (стековых переменных) нельзя использовать за функцией, т.к. их распределяет (аллоцирует/освобождает) компилятор, а время их жизни ограничено их областью видимости
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]