Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.77/22: Рейтинг темы: голосов - 22, средняя оценка - 4.77
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21286 / 8311 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30

Избыточное копирование объекта при реализации оператора умножения и оператора присваивания

21.03.2016, 18:43. Показов 6114. Ответов 84
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть класс работы с матрицами. Есть операция умножения матриц, описанная как оператор класса. В данном коротком примере я просто моделирую ситуацию. Реальное наполнение класса принципиальной разницы не играет, нужно просто понимать, что оператор умножения будет иметь большой код, оператор присваивания в реализации тоже будет не пустым. Эти места в примере засвечены комментариями

C++
#include <cstdio>
 
class Matrix
{
  private:
    // внутренние данные матрицы
 
  public:
    Matrix ();
    Matrix (const Matrix&);
    ~Matrix ();
 
    Matrix& operator=(const Matrix& a);
    Matrix operator*(const Matrix& a) const;
};
 
Matrix::Matrix ()
{
  printf ("Matrix ()\n");
};
 
Matrix::Matrix (const Matrix&)
{
  printf ("Matrix (const Matrix&)\n");
};
 
Matrix::~Matrix ()
{
  printf ("~Matrix ()\n");
};
 
Matrix& Matrix::operator=(const Matrix& a)
{
  printf ("operator=(const Matrix&)\n");
 
  // тут как бы код, копирущий данные из "a" в "this"
 
  return *this;
}
 
Matrix Matrix::operator*(const Matrix& a) const
{
  printf ("operator*(const Matrix&)\n");
 
  Matrix result;
 
  // тут как бы код, умножающий "a" и "this" и записывающий
  // данные в "result"
 
  return result;
}
 
Matrix a, b, c;
 
int main (void)
{
  printf ("------------------\n");
  a = b * c;
  printf ("------------------\n");
}
Исполнение:

Code
$ g++-4.8 t.cc
$ ./a.out
Matrix ()
Matrix ()
Matrix ()
------------------
operator*(const Matrix&)
Matrix ()
operator=(const Matrix&)
~Matrix ()
------------------
~Matrix ()
~Matrix ()
~Matrix ()
Нас интересует только фрагмент печати внутри функции main (т.е. между палками)

Посмотрим на ассемблерный код. Компилирую с опцией -fno-inline, чтобы оставаться с короткой программой и не разводить геморрой по борьбе с inline'ом со стороны компилятора. В общем случае тела операторов класса Matrix будут в отдельном файле и НЕ будут доступны для inline'а. Опцию -fno-exceptions подаю, чтобы было меньше мусора в коде

Code
$ g++ t.cc -O2 -fno-inline -fno-exceptions
$ cat t.s
...
    leal    -9(%ebp), %ebx
    subl    $32, %esp
    movl    %ebx, (%esp)
    movl    $c, 8(%esp)
    movl    $b, 4(%esp)
    call    _ZN6MatrixmlERKS_  <- operator*
 
    subl    $4, %esp
    movl    %ebx, 4(%esp)
    movl    $a, (%esp)
    call    _ZN6MatrixaSERKS_  <- operator=
...
Таким образом мы видим, что построился код, схематично эквивалентный следующему примеру на Си. На всякий случай напоминаю, что с точки зрения семантики C++ выражение "a = b * c" трактуется как "a.operator= (b.operator* (c))"

C
typedef struct { /* внутренности */ } Matrix;
 
extern void operator_assign (Matrix *this, const Matrix *value);
extern void operator_mul (Matrix *result, const Matrix *this, const Matrix *operand2);
 
Matrix a, b, c;
 
int main (void)
{
  Matrix tmp;
 
  operator_mul (&tmp, &b, &c); /* tmp = b.operator* (c) */
  operator_assign (&a, &tmp);  /* a.operator= (tmp) */
}
Мы видим, что в этом коде делается ненужное действие в виде лишнего оператора присваивания. Для умножения матриц эффективный код на Си выглядел бы как

C
operator_mul (&a, &b, &c);
т.е. без заведения промежуточной переменной и дополнительного копирования (которое представляет собой ненужные накладные расходы)

Вопрос. Как правильно написать текст на C++, чтобы получить код, эквивалентный вышеприведённой эффективной реализации на C? Оставаясь при этом в объёме стандарта C++98. Оставляя исходник в понятном и читабельном виде, без использования извращений типа семиэтажных шаблонов и т.п.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
21.03.2016, 18:43
Ответы с готовыми решениями:

Неправильная работа оператора присваивания после работы оператора суммирования
Доброго времени суток. У меня есть класс вектор class TVector {//ewde public: TVector(); //Vector(Vector &amp;v); ...

От каких ошибок страхует Const при перегрузке оператора присваивания
Здравствуйте. Вопрос имею теоретический. В классе A перегружается оператор присваивания, объявление выглядит так: const A operator =...

Почему при перегрузке оператора присваивания, возвращаемое значение не константно?
Почему при перегрузке оператора присваивания, возвращаемое значение - someClass &amp; operator=(const someClass&amp; rhl), а не const...

84
 Аватар для icpu
487 / 365 / 93
Регистрация: 10.03.2011
Сообщений: 1,513
Записей в блоге: 5
24.03.2016, 12:55
Студворк — интернет-сервис помощи студентам

Не по теме:

Evg, Nosey, я, конечно, понимаю, серьёзные дядьки ведут серьёзные споры, но позвольте мне вбросить свои 5 копеек.


Цитата Сообщение от Evg Посмотреть сообщение
Вопрос. Как правильно написать текст на C++, чтобы получить код, эквивалентный вышеприведённой эффективной реализации на C? Оставаясь при этом в объёме стандарта C++98. Оставляя исходник в понятном и читабельном виде, без использования извращений типа семиэтажных шаблонов и т.п.
D-pointers и следующее за ними ленивое выделение памяти при копировании, которая в Qt любовно завётся Implicit Sharing. В нагрузку незаслуженно получаем ещё и бинарную совместимость.
Минусы - все объекты на куче, код хуже инлайнится и лишние 12 (+shared_ptr+mutex++) байт на хранение адреса и флага владением.
Пример приводить не буду, гугль справится лучше. Или дока куты.

Не по теме:

Dixi

0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21286 / 8311 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
24.03.2016, 14:24  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Ну да, а ты что не можешь так?
А какая тебе разница, применять ctrl-c к статической библиотеке, или к динамической

Цитата Сообщение от Nosey Посмотреть сообщение
Чем же макросы в этой задаче помогут?
Макросом реализуется тело, а затем подставляется либо вовнутрь класса, либо в отдельный модуль. Либо пишется inline-тело в *.h файле, а затем макросом подставляется в нужное место

Цитата Сообщение от Nosey Посмотреть сообщение
Может для тебя оно и так, мои познания асма не далеко ушли с момента института
Я интеловскую архитектуру не знаю совсем. И это мне совсем не помешало увидеть разницу в двух сгенерированых кодах

Цитата Сообщение от Nosey Посмотреть сообщение
без lto : (C-подход) < (CPP inline) < (CPP noInline) - тут везде минимальный отрыв с максимумом в 5%.
с lto : (CPP inline) < (CPP noInline) < (C-подход) - тут ровно то что я указывал ранее, C-подход отстает очень знатно
А что, даже такие результаты тебе не показались сомнительными?

Цитата Сообщение от Nosey Посмотреть сообщение
Точно ли адекватно проводился тест (cpu был свободен)?
С твоего позволения, сделаю вид, что вопроса не заметил

Цитата Сообщение от Nosey Посмотреть сообщение
Что за версия gcc? Что за cpu? Как насчет -march=native для всех тестов?
Не помню, что за версия, дома запускал. Какая разница какой cpu? Опция -flto условно объединяет исходники из нескольких файлов в одном запуске компилятора, таким образом становится доступным межмодульный инлайн. Инлайн - машинно-независимая оптимизация, ей плевать, какие там настройки cpu

Цитата Сообщение от Nosey Посмотреть сообщение
А ты можешь объяснить хотябы -О2?
Могу

Цитата Сообщение от Nosey Посмотреть сообщение
Что-то не понял о чем это ты
Конкретно я взял и запустил "-O3 -flto", получив при этом ухудшение. При этом нет никакой гарантии, что в один прекрасный момент ты не получишь тот же самый результат в какой-то из своих боевых программ, написанных "криво" (с точки зрения идеологии Си++), в рассчёте на то, что режим -flto сумеет победить кривизну. При этом ты не сможешь победить проблему, потому как не знаешь реальный источник проблемы. И отключение опции -flto уже не поможет, т.к. программа написана "криво". Всё это я к тому, что проектировать программу, закладываясь на режим -flto, это в общем-то сомнительное занятие
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
24.03.2016, 15:56
Цитата Сообщение от Evg Посмотреть сообщение
А какая тебе разница, применять ctrl-c к статической библиотеке, или к динамической
Потому что это действие изменит тип линковки.

Цитата Сообщение от Evg Посмотреть сообщение
Макросом реализуется тело, а затем подставляется либо вовнутрь класса, либо в отдельный модуль. Либо пишется inline-тело в *.h файле, а затем макросом подставляется в нужное место
Этому больше не наливать.
Как ты собрался при помощи макросов перенести код с одной единицы трансляции в другую? Ведь суть этой нашей подветки была в этом.

Цитата Сообщение от Evg Посмотреть сообщение
Я интеловскую архитектуру не знаю совсем. И это мне совсем не помешало увидеть разницу в двух сгенерированых кодах
Я тоже хотел бы так, но я не могу за 10 минут однозначно разобраться. Также это не имеет большого смысла для общего случая, поэтому я не рвусь за такими способностями.

Цитата Сообщение от Evg Посмотреть сообщение
А что, даже такие результаты тебе не показались сомнительными?
Мои результаты - в пределах здравого смысла. И говорят о том, что "оверхед от копирования при С++ подходе сводится к минимуму, либо отсутствует, и что технология LTO работает", но я не предлагаю ни кому возвращать что-то толстое по значению, в надежде на оптимизацию, ни в коем случае, и не говорю что если ты будешь писать как буратино компилятор спасет тебя.

Цитата Сообщение от Evg Посмотреть сообщение
Не помню, что за версия, дома запускал. Какая разница какой cpu? Опция -flto условно объединяет исходники из нескольких файлов в одном запуске компилятора, таким образом становится доступным межмодульный инлайн. Инлайн - машинно-независимая оптимизация, ей плевать, какие там настройки cpu
Вот именно, как тогда можно катить бочку на LTO, говоря что она замедляет код, тебе опять налили?
Остается по факту вариант, что у тебя древний gcc, с преальфой LTO? Другие варианты, при условии правильного проведенного теста, слишком неправдоподобны, и один сложен в раскопках - разбираться что lto сгенерил что-то страшное именно для твоей архитектуры.

Цитата Сообщение от Evg Посмотреть сообщение
Могу
Случаем компилятором не подрабатываете? А зачем ты тогда вообще асм выхлоп смотрел, если и так все знал?

Цитата Сообщение от Evg Посмотреть сообщение
Конкретно я взял и запустил "-O3 -flto", получив при этом ухудшение.
Эти аномальные результаты - для меня полная загадка, у меня таких результатов и близко не было, LTO однозначно ускорял код, при недоступном инлайнинге(использовании Math.cpp). И я хотел бы узнать подробней об этой ситуации, но все мои тесты не дают какой-либо инфы.

Цитата Сообщение от Evg Посмотреть сообщение
При этом нет никакой гарантии, что в один прекрасный момент ты не получишь тот же самый результат в какой-то из своих боевых программ, написанных "криво" (с точки зрения идеологии Си++), в рассчёте на то, что режим -flto сумеет победить кривизну.
Однозначно, это не панацея, это хороший инструмент, которым грех не пользоваться.
А гарантии ровно такие же, как использование купленной библиотеки, т.е. никаких гарантий.

Цитата Сообщение от Evg Посмотреть сообщение
При этом ты не сможешь победить проблему, потому как не знаешь реальный источник проблемы.
Т.е. ты считаешь что если кто-то добавил к gcc флаг -flto, то мозг у этого человека отключается за ненадобностью? И что профайлеры удаляются с его компа?
Это инструменты которые позволяют писать код легче и удобней, практически не жертвуя как производительностью кода, так и сроками разработки в случае "проблем", почему мы должны от них отказываться?

Цитата Сообщение от Evg Посмотреть сообщение
Всё это я к тому, что проектировать программу, закладываясь на режим -flto, это в общем-то сомнительное занятие
Я чувствую в этом сообщении уже не ту критичность которая была парой страниц назад, это хорошо.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21286 / 8311 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
24.03.2016, 16:47  [ТС]
Цитата Сообщение от Nosey Посмотреть сообщение
Потому что это действие изменит тип линковки
Цитата Сообщение от Nosey Посмотреть сообщение
Этому больше не наливать.
Как ты собрался при помощи макросов перенести код с одной единицы трансляции в другую? Ведь суть этой нашей подветки была в этом.
Это оставлю без внимания. Нет желания рассказывать азбучные истины

Цитата Сообщение от Nosey Посмотреть сообщение
Мои результаты - в пределах здравого смысла. И говорят о том, что "оверхед от копирования при С++ подходе сводится к минимуму, либо отсутствует, и что технология LTO работает"
Нету в них здравого смысла. При правильно написанном тесте и правильно работающем компиляторе результатом было бы равенство времени исполнения двух подходов (вариант С++ без инлайна, разумеется, отбрасываем как заведомо несимметричный). Поскольку равенства не наблюдается, то либо тест написан неправильно (сие имеет место быть), либо компилятор работает не правильно (либо у режима -flto есть какие-то тонкости). Чудес-то не бывает. Думать, что C++ чем-то лучше C в условиях полного инлайна со стороны компилятора - детская наивность

Цитата Сообщение от Nosey Посмотреть сообщение
от именно, как тогда можно катить бочку на LTO, говоря что она замедляет код
Я тебе привёл факты - конкретные числа, полученные в конкретном замере. Ты, конечно, можешь заподозрить, что я что-то там намухлевал, но в таких условиях вообще нет смысла продолжать разговор. Когда есть факты, их надо уметь объяснить. Лично мне эти факты ни разу не интересны, т.к. я для себя вообще не вижу никакой практической необходимости в режиме -flto. Ты эти факты, думается, объяснить тоже не сможешь. Однако по итогу этого замера я могу сказать одно - этот замер показывает непонятно что и доказывает (я так понял, что он должен был что-то доказать) тоже непонятно что

Цитата Сообщение от Nosey Посмотреть сообщение
Однозначно, это не панацея, это хороший инструмент, которым грех не пользоваться.
А гарантии ровно такие же, как использование купленной библиотеки, т.е. никаких гарантий
Ещё раз. Режим LTO - это инструмент для выпрямление кривого исходника целиковой программы. К библиотекам, поставляемым в виде бинарников этот инструмент не применим по определению

Цитата Сообщение от Nosey Посмотреть сообщение
Т.е. ты считаешь что если кто-то добавил к gcc флаг -flto, то мозг у этого человека отключается за ненадобностью?
Если опция -flto дала значительный прирост, это говорит в первую очередь о кривом проектировании программы. Можно ли что-то в таком случае говорить о мозге - я не знаю, ибо не психиатор

Цитата Сообщение от Nosey Посмотреть сообщение
Это инструменты которые позволяют писать код легче и удобней, практически не жертвуя как производительностью кода, так и сроками разработки в случае "проблем", почему мы должны от них отказываться?
Да не вопрос, живи на -flto, работай в колхозе под условием "наш софт будет хорошо работать только на gcc (причём только в связке с gld), в котором есть опция -flto"

Цитата Сообщение от Nosey Посмотреть сообщение
Я чувствую в этом сообщении уже не ту критичность которая была парой страниц назад, это хорошо
Критичности нет по следующей причине. Очень часто возникает потребность быстро что-то сделать "на коленке". Когда попросту нет времени и необходимости думать над проектированием программы. Тогда можно в общем-то положиться и на -flto, понимая при этом, что ты выпускаешь не программный продукт, а поделку. Если ты не хочешь думать о правильном проектировании конечного программного продукта - тебе виднее
0
 Аватар для Nosey
1379 / 406 / 144
Регистрация: 22.10.2014
Сообщений: 872
24.03.2016, 18:06
Цитата Сообщение от Evg Посмотреть сообщение
Это оставлю без внимания. Нет желания рассказывать азбучные истины
Сказочная страна, азбука по черной магии.
Цитата Сообщение от Evg Посмотреть сообщение
При правильно написанном тесте и правильно работающем компиляторе результатом было бы равенство времени исполнения двух подходов
Если бы ты читал сообщения, и не переводил тему каждый раз и не вносил новые условия работы кода, то ты бы заметил что у меня в правильной ситуации все именно так.
Цитата Сообщение от Evg Посмотреть сообщение
Чудес-то не бывает.
Конечно, именно поэтому я не верю в чёрную магию.
Цитата Сообщение от Evg Посмотреть сообщение
Думать, что C++ чем-то лучше C в условиях полного инлайна со стороны компилятора - детская наивность
Детсвкая наивность это считать что компилятор всемогущ, и сможет заинлайнить одинаково хорошо код с использованием локальных переменных с малым и однозначным для него временем жизни, и непонятно откуда прилетевшие указатели, через 20 единиц трансляции, да еще и без lto.
Цитата Сообщение от Evg Посмотреть сообщение
Ты, конечно, можешь заподозрить, что я что-то там намухлевал, но в таких условиях вообще нет смысла продолжать разговор.
С учетом твоих сообщений в которых грань между конструктивностью и тролингом очень тонка - да, возникают такие мысли, но я как порядочный гражданин гоню их и пытаюсь найти объяснение.
Цитата Сообщение от Evg Посмотреть сообщение
Когда есть факты, их надо уметь объяснить.
Но я не могу их объяснить, извиняй, не могу. В идеале хотелось бы какой-то инфы от тебя, но от тебя инфы отличной от "все кругом гондоны, а я воздушный шарик" не вижу.(это не лично, это касательно технологий)
Цитата Сообщение от Evg Посмотреть сообщение
К библиотекам, поставляемым в виде бинарников этот инструмент не применим по определению
Где я говорил про применение LTO в данном случае? Я говорил о ГАРАНТИЯХ. Вот какие гарантии у тебя есть используя библиотеку? Есть ли в списке гарантия что библиотека самая лучшая из всех возможных? Так почему ты ждешь магических гарантий от LTO? Хватит кидаться в крайности и искать оправдания, да причины.
Цитата Сообщение от Evg Посмотреть сообщение
Если опция -flto дала значительный прирост, это говорит в первую очередь о кривом проектировании программы.
Вот и попробуй собрать свой рабочий проект с lto, посмотрим насколько кривая архитектура у вас.
Цитата Сообщение от Evg Посмотреть сообщение
Да не вопрос, живи на -flto, работай в колхозе под условием "наш софт будет хорошо работать только на gcc (причём только в связке с gld), в котором есть опция -flto"
Колхоз? Такой же колхоз присутствует в шланге, в студийном компиляторе, в gcc этому колхозу уже 7 лет. Такая редкость сегодня, 7 лет это конечно маловато для того чтобы обратить внимание на технологию.

Цитата Сообщение от Evg Посмотреть сообщение
Критичности нет по следующей причине. Очень часто возникает потребность быстро что-то сделать "на коленке". Когда попросту нет времени и необходимости думать над проектированием программы. Тогда можно в общем-то положиться и на -flto, понимая при этом, что ты выпускаешь не программный продукт, а поделку. Если ты не хочешь думать о правильном проектировании конечного программного продукта - тебе виднее
Ну, я могу согласиться с парой натяжек.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
24.03.2016, 18:06

Какое значение получит переменная p при выполнении следующего оператора присваивания?
var p: set of 0..9; i, j: integer; Если i=2 и j=5, то какое значение получит переменная p при выполнении следующего оператора...

Ошибка при выполнении оператора присваивания производного класса через указатель на базовый
Здравствуйте, не могу понять из-за чего ошибка. Надо в производном классе объявить оператор сложения и обратится к нему через базовый. ...

Ошибка при реализации перегрузки оператора <<
Добрый день. Прошу помощи. Имеется такой класc. class DList { ... public: ... void Save(std::ofstream &amp;b_out); //...

Ошибка в вводе данных из HTML и переносе их в JavaScript, при выполнении оператора IF или оператора swithc
доброго времени суток, при выполнении одной учебной задачи столкнулся с проблемой: при введении любого значения в поле, код выдает только...

Переопределение оператора присваивания
Имеется такой простой класс: class TClass { private: float* A; int N; public: TClass(int _N) ...


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

Или воспользуйтесь поиском по форуму:
85
Ответ Создать тему
Новые блоги и статьи
Генератор паролей (вариант №1)
Maks 29.10.2026
Реализация из решения ниже выполнена исключительно по моей инициативе, дабы облегчить себе работу в создании паролей для администрируемых мною сервисов и пользователей. Самым главным критерием для. . .
Установка ChatGPT (Codex) на Windows без использования Microsoft Store
Fabien159 28.10.2026
Здравствуйте всем читающим! Опишу процесс установки ChatGPT (Codex) на Windows, если по каким-то причинам у вас не получается устанавить его через Microsoft Store. И так: 1. Скачиваем с. . .
Программное добавление префикса в нумерацию документов
Maks 27.10.2026
Реализация из решения ниже выполнена в самописной конфигурации на БСП (помощь начинающему коллеге). Задача: Программно добавить префикс в нумерацию документов. Решение: В модуле объекта. . .
После закрытия оутлука продолжает висеть процесс в диспетчере задач
Maks 27.10.2026
С недавнего времени в продакшене возникла проблема: при закрытии оутлука в диспетчере задач продолжал висеть процесс outlook. exe. Проблема возникла после установки MS Office 2021 LTSC на машинах, под. . .
Baragoz - DPS/HPS бот для WoW 3.3.5a, многоязычный
AmbA 26.10.2026
Хотите ещё ботов? У меня есть один! А я пока отдохну от него. https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=12062&stc=1&d=1793007952 Инструкция внутри. https:/ / youtu. be/ VpfFZSUDGnQ. . .
Особенности gif сгенерированных в Си
russiannick 21.10.2026
Рассмотрим генерацию gif файлов, которые в Си имеют свои особенности. Gif представляет собой графический формат популярный в интернете. Посмотрим на палитру. Gif файл сгенерированный в си отличается. . .
FPS контроллер с анимированными Y-Bot и 3D-звуком miniaudio (Box3D, Recast, BehaviorTree.CPP, ozz-animation, ImGui, OpenGL и SDL3)
8Observer8 18.10.2026
Содержание блога | English Version Полное мультиплатформенное руководство по стартовому проекту с FPS-контроллером игрока, анимированными роботами Y-Bot с 4-слойным блендингом, 3D-физикой Box3D,. . .
Локальный http сервер
Argus19 17.10.2026
Локальный http сервер На работе, на двух локальных компьютерах круглосуточно работают программы опроса приборов с записью в книги Excel,которые раз в сутки записываются на сервер компании. Т. к. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru