Копировать конструктор не вызывается в результате функции - PullRequest
6 голосов
/ 30 августа 2011

GCC содержит утверждение - как бы я ни старался его предотвратить. Я пытался

  • -fno-inline
  • -O0
  • __attribute__ ((noinline))
  • dummy asm("")

Нет успеха! Вот код:

#include<iostream>

using namespace std;

struct A {
  A() {cout << "A::A()" <<endl; }
  A(const A& a) {cout << "A::A(copy)" <<endl; }
  A& operator=(const A& a) {cout << "A::=()" <<endl; return *this;}
};

A __attribute__ ((noinline)) func() 
{
  cout << "func()" << endl;
  A loc;
  asm("");
  return loc;
}

int main() {
  A a = func();
}

Неудачный вывод этого (g ++ (Ubuntu / Linaro 4.5.2-8ubuntu4) 4.5.2) равен

func()
A::A()

Что случилось с оператором A a = func (); ??

Причина этого эксперимента в том, что я хотел бы знать, что происходит, когда выполнение приходит к этому утверждению (потому что мне нужно контролировать, как это делается):

A a = func();

Я прочитал, что конструктор копирования вызывается, когда кто-то

A a = b;

(В этом случае вызывается конструктор копирования. Но не в случае A a = func ();) Функция встроена вместо. Я NEED контролирую это утверждение, так как моя "структура А" в реальной жизни содержит динамически распределяемые данные, о которых нужно позаботиться.

Я что-то упускаю здесь очевидное? *

Ответы [ 3 ]

18 голосов
/ 30 августа 2011

Нет, это не имеет ничего общего с функцией встраивания.Встраивание функции не изменит наблюдаемого поведения.

Эта оптимизация называется elision copy, которая позволяет компилятору избежать копирования, создавая возвращаемое значение непосредственно в месте назначения.Вы можете отключить его с помощью флага g ++ -fno-elide-constructors.

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

6 голосов
/ 30 августа 2011

Если struct A содержит динамически распределяемые данные, то вы несете ответственность за управление этой памятью в соответствующем деструкторе / конструкторе.Многие классы управляют динамически распределяемыми данными и прекрасно работают с удаленными копиями.RVO и NRVO - важные оптимизации.

3 голосов
/ 16 апреля 2018

В случае, если кто-то (как я) действительно хочет избежать inline:

-fkeep-inline-functions -fno-inline

-fkeep-инлайн-функции
Даже если все вызовы данной функции интегрированы, а функция объявлена ​​как статическая, тем не менее, выдается отдельная вызываемая во время выполнения версия функции. Этот переключатель не влияет на внешние встроенные функции.

-fno-рядный
Не обращайте внимания на встроенное ключевое слово. Обычно эта опция используется, чтобы не допустить расширения компилятором встроенных функций. Обратите внимание, что если вы не оптимизируете, никакие функции не могут быть развернуты встроенными.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...