Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Конструктора копирования, и оператор &  
V
    Опции темы
Zhunko
Дата 30.11.2012, 02:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Код

class A
 {
  int k;
  int n[2];
  public:
  A()
   {
    k = 0;
    n[0] = 123;
    n[1] = 345;
   }
  virtual ~A(){}
  A &operator[](int i)
   {
    k = i;
    return(*this);
   }
  A(const A &a){} // Без конструктора копирования работает правильно.
  operator int&()
   {
    return(n[k]);
   }
 };

template<class T> // Если закоментировать шаблон и жёстко задать тип int, работает правильно. Даже с конструктором копирования.
int MyFunc(T tIndex)
 {
  return(tIndex);
 }

void _tmain(int argc, LPTSTR argv[], LPTSTR envp[])
 {
    A a;
    std::vector<int> v(2, 123);
    v[1] = 456;
    tcout << a[0] << a[1] << ENDL; // Контрольный вывод для сравнения. Работает.
    tcout << MyFunc(a[0]) << MyFunc(a[1]) << ENDL; // Не работает!
    tcout << MyFunc<int>(a[0]) << MyFunc<int>(a[1]) << ENDL; // Так работает.
    tcout << MyFunc(v[0]) << MyFunc(v[1]) << ENDL; // Это всегда работало.
  }

В идеале два первых вывода должны быть одинаковы.
Но в случае наличия конструктора копирования работает неправильно. После вызова конструктора копирования оператор & не вызывается. Компилятор считает, что передаю класс А, а не число типа int.
В std::vector это каким-то образом сделано. Разбирался так и не понял. Там так всё просто, что зацепиться не за что.
Что надо сделать, чтобы конструктор копирования работал и оператор & после него вызывался?

Это сообщение отредактировал(а) Zhunko - 30.11.2012, 02:20
PM MAIL   Вверх
math64
Дата 30.11.2012, 07:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 8
Всего: 72



Ты объявил пустой коструктор копирования, который ничего не делает. естественно не работает.
Если коструктор копирования не объявлен, компилятор сделает его за тебя.
В данном случае сгенирированый компилятором конструктор будет правильным, и всё будет работать правильно.
PM   Вверх
Zhunko
Дата 30.11.2012, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Это для простоты восприятия таким показал конструктор копирования.
У меня в основном коде, откуда сделал упрощённый пример, такой:
Код

A(const A &a)
 {
   Init(a); // Полностью иициализирует класс.
 }

Это тоже не работает.
Тогда, какой должен быть конструктор копирования?
PM MAIL   Вверх
xvr
Дата 30.11.2012, 12:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(Zhunko @  30.11.2012,  02:18 Найти цитируемый пост)
После вызова конструктора копирования оператор & не вызывается. 

У вас нет оператора &, а есть у вас оператор приведения типа к int& (и он скорее всего вызывается)


PM MAIL   Вверх
Zhunko
Дата 30.11.2012, 12:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Цитата
После вызова конструктора копирования оператор & не вызывается.
У вас нет оператора &, а есть у вас оператор приведения типа к int& (и он скорее всего вызывается) 

Вызывается в случае отсутствия явного коструктора копирования. В остальных случаях игнорируется.
PM MAIL   Вверх
volatile
Дата 30.11.2012, 15:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Zhunko @  30.11.2012,  02:18 Найти цитируемый пост)
в случае наличия конструктора копирования работает неправильно

Прямой вывод => ваш конструктор копирования неверен. и это без вариантов.  smile 
как правильно сказал math64, 
Цитата(math64 @  30.11.2012,  07:44 Найти цитируемый пост)
Если коструктор копирования не объявлен, компилятор сделает его за тебя.

В программе всегда есть конструктор копирования, либо ваш, либо дефолтный.
С вашим не работает, с дефолтным работает ==> ...   что из этого следует ?

Хотя в коде дофига и другой путаницы.
например, непонятно зачем оператор [] возвращает сам объект.
но это уже второстепенно.

Добавлено через 7 минут и 27 секунд
вот, написал простеньки конст.коп. 
http://codepad.org/gd6BJTpF

что не работает ?

PM MAIL   Вверх
Zhunko
Дата 30.11.2012, 18:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Спасибо! Ваш код работает. Нашёл чего не хватало у меня. Не все члены класса инициализировались. Как раз те, что отвечали за индекс, не добавил. Init() один раз написал и забыл.

Цитата(volatile @  30.11.2012,  16:43 Найти цитируемый пост)
Хотя в коде дофига и другой путаницы. например, непонятно зачем оператор [] возвращает сам объект.но это уже второстепенно.

На счёт возврата оператором [], спасибо! Глаз замылился. smile  Почему-то посчитал, что так лучше будет. Переделываю... 

Написал класс-оболочку над std::vector для работы с ним, как с многомерным динамическим массивом. Можно менять количество измерений на ходу без нарушения структуры данных. Есть возможность передавать указатель или ссылку на начало массива. Т.е. данные непрерывны. Тесты все прошёл, а, как попытался в качестве аргумента функции с шаблонным типом передать содержимое ячейки - ошибка.

Это сообщение отредактировал(а) Zhunko - 30.11.2012, 18:40
PM MAIL   Вверх
borisbn
Дата 30.11.2012, 18:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(Zhunko @  30.11.2012,  18:04 Найти цитируемый пост)
Написал класс-оболочку над std::vector для работы с ним, как с многомерным динамическим массивом.

буст переписывашь ?
http://www.boost.org/doc/libs/1_52_0/libs/...y/doc/user.html


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Zhunko
Дата 30.11.2012, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Цитата(borisbn @  30.11.2012,  19:50 Найти цитируемый пост)
буст переписывашь ?

Буст смотрел. У меня круче и интерфейс проще. smile Буст не позволяет менять количество измерений. По моему, там нарушается структура данных при манипуляциях с размерами. У меня 64 перегрузки операторов для групповых операций с элементами массива. Есть копирование многомерный->многомерный с сохранением структуры данных. Куда покажешь - туда скопирует фрагмент массива.

Цитата(Zhunko @  30.11.2012,  19:04 Найти цитируемый пост)
На счёт возврата оператором [], спасибо! Глаз замылился.   Почему-то посчитал, что так лучше будет. Переделываю... 

Не вышло. Сначала правильно сделал. Это, если один оператор [] и он возвращает содержимое ячейки, то всё красиво выходит. Если много [], то не компилируется. Ему же требуется класс-объект, а не содержимое ячейки.

Сейчас всё работает. Спасибо всем! Особенно volatile!
Но последний вопрос остаётся.
Посмотрел в дебаггере. Всё же:
Код

tcout << MyFunc(a[0]) << MyFunc(a[1]) << ENDL;

a[0] функция получает, как класс A, а не число-значение (123) указанного типа int. Это потом срабатывает перегрузка
Код

operator int&(){}

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

Это сообщение отредактировал(а) Zhunko - 30.11.2012, 20:10
PM MAIL   Вверх
volatile
Дата 1.12.2012, 00:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Zhunko @  30.11.2012,  19:21 Найти цитируемый пост)
Не вышло. Сначала правильно сделал. Это, если один оператор [] и он возвращает содержимое ячейки, то всё красиво выходит. Если много [], то не компилируется. Ему же требуется класс-объект, а не содержимое ячейки.

Вы вообще о чем? Вы серьезно считаете что здесь собрались исключительно экстрасенсы-телепаты ?

Цитата(Zhunko @  30.11.2012,  19:21 Найти цитируемый пост)
a[0] функция получает, как класс A, а не число-значение (123) указанного типа int ... Как сделать так, чтобы компилятор сразу воспринимал аргумент, с типом содержимого ячейки массива?

Вы возвращаете из оператора [] ссылку на А, компилятор и воспринимает ее как ссылку на А.
По моему, весьма логично. И что-то другое требовать от компилятора, как-то даже странно...

Цитата(Zhunko @  30.11.2012,  19:21 Найти цитируемый пост)
Буст смотрел. У меня круче и интерфейс проще.

Охотно верю, но по коду что вы привели, этого, мягко говоря, пока не скажешь.

PM MAIL   Вверх
baldina
Дата 1.12.2012, 00:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Zhunko, буст конечно отстой по сравнению с вашим классом,  но я о другом хотел спросить: приведите плиз пример задачи, для решения которой нужен ваш класс, т.е. для чего нужен многомерный массив с изменяемыми размерностями?
PM MAIL   Вверх
volatile
Дата 1.12.2012, 00:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



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

у bsa есть хорошая фраза в подписи
Цитата

Правильно заданный вопрос - половина ответа



PM MAIL   Вверх
Zhunko
Дата 1.12.2012, 04:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Цитата(volatile @  1.12.2012,  01:27 Найти цитируемый пост)
Вы вообще о чем? Вы серьезно считаете что здесь собрались исключительно экстрасенсы-телепаты ?

Да уж, яснее некуда объяснил. Имел ввиду несколько операторов [] подряд для такого обращения к многомерному массиву:
Код

int main ()
 {
    A a; // Для нетелепатов. Это не тот класс, что выше опубликован. Это пример нереализованного здесь класса многомерного массива.
    std::cout << a[0][1][2][3] << std::endl;
  }

Здесь компилятор требует к оператору [] массив или указатель. Так, что вернуть содержимое ячейки не получится для нескольких [].

Цитата(volatile @  1.12.2012,  01:27 Найти цитируемый пост)
Вы возвращаете из оператора [] ссылку на А, компилятор и воспринимает ее как ссылку на А.По моему, весьма логично. И что-то другое требовать от компилятора, как-то даже странно...

Ну нельзя, значит нельзя. Не настаиваю. smile 

Цитата(volatile @  1.12.2012,  01:27 Найти цитируемый пост)
Охотно верю, но по коду что вы привели, этого, мягко говоря, пока не скажешь.

Где код привёл?  smile  Ни строчки не выложил ещё. Всё, что здесь написал, это простые примеры демонстрации проблемы. Да и проблема-то ерундовая. Забыл пару переменных инициализировать.

Цитата(baldina @  1.12.2012,  01:39 Найти цитируемый пост)
Zhunko, буст конечно отстой по сравнению с вашим классом,  но я о другом хотел спросить: приведите плиз пример задачи, для решения которой нужен ваш класс, т.е. для чего нужен многомерный массив с изменяемыми размерностями?

Про отстой, заметьте, не я сказал  smile 
Есть такой язык MQL4. Там данные можно объединить только в массивы. Память, которой можно пользоваться, только недавно сделали 4 Гб. До этого было всего 2 Гб. Данные, которые требуется обрабатывать, составляют десятки Гб. На данный момент программный комплекс у меня обрабатывает максимум 5-мерный массив. Приходится по-всякому экономить. Хорошо, что ещё DLL разрешили подключать, а то совсем плохо было бы. В перспективе надо выводить расчёты за пределы MQL4. Тогда таких ограничений не будет. Но это непросто сейчас. Пока работает и так. Есть более важные задачи.

Кстати, реализация, как у буста, у меня тоже есть. Такой же параметр шаблона для объявления количества измерений. Только этот параметр у меня инициализирован по умолчанию и ограничивает максимальное количество измерений. Т.е. можно работать с ним, как с жёстко заданным количеством измерений, так и с изменяемым.

Цитата(volatile)

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

Нет проблемы. Нечего формулировать. Всё работает. Спасибо!

Это сообщение отредактировал(а) Zhunko - 3.12.2012, 03:51
PM MAIL   Вверх
volatile
Дата 1.12.2012, 14:18 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2107
Регистрация: 7.1.2011

Репутация: 37
Всего: 85



Цитата(Zhunko @  1.12.2012,  04:30 Найти цитируемый пост)
  std::cout << a[0][1][2][3] << std::endl;

В этой строчке, получается, у вас объект в правой стороне выражения изменяется 3 раза?
Поверьте, такой side-effect, мало кто, готов ожидать. 

Zhunko, я конечно не знаю что вы там пишите, но имхо, интутивно чувствую что вы делаете что-то не то.
например
Код

v = a[1] + a[2];
В этой строчке у вас объект (a) будет изменяться 2 раза, причем порядок изменения неопределен, по стандарту это УБ.
я уж не говорю про то, что он вообще в принципе никогда не может быть rvalue.
В общем, проблем на свою голову вы найдете...



PM MAIL   Вверх
Zhunko
Дата 1.12.2012, 16:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 75
Регистрация: 4.11.2009

Репутация: нет
Всего: нет



Цитата(volatile @  1.12.2012,  15:18 Найти цитируемый пост)
Цитата(Zhunko @  1.12.2012,  04:30 )
Код

  std::cout << a[0][1][2][3] << std::endl;

В этой строчке, получается, у вас объект в правой стороне выражения изменяется 3 раза?
Поверьте, такой side-effect, мало кто, готов ожидать. 

4 раза будет меняться.

Цитата(volatile @  1.12.2012,  15:18 Найти цитируемый пост)
Zhunko, я конечно не знаю что вы там пишите, но имхо, интутивно чувствую что вы делаете что-то не то.например
Код

v = a[1] + a[2];

В этой строчке у вас объект (a) будет изменяться 2 раза, причем порядок изменения неопределен, по стандарту это УБ.я уж не говорю про то, что он вообще в принципе никогда не может быть rvalue.В общем, проблем на свою голову вы найдете...

К сожалению, такая арифметика для класса не доступна. Пока не знаю, как это сделать.
Правильнее сказать, знаю, как сделать некрасиво. Например, перегрузить [] с парой типов аргумента. Завершающий оператор вызывать с конкретным типом.
Лучше не буду так делать, чем иметь возможность складывать содержимое ячеек с индексацией в [].
Хотя, в этом что-то есть. Таким образом, можно частично на компилятор возложить слежение за правильностью применения []. Отслеживание количества [] сам класс делает.

Зато есть метод At(), с которым такая арифметика работает:
Код

v =  a.At(0, 1, 2, 3) + a.At(3, 2, 1, 0);


Это сообщение отредактировал(а) Zhunko - 1.12.2012, 21:52
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0600 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.