Почему копия ctor используется в этом коде?

if let fbSDKAppId = FBSDKSettings.appID(),
            url.scheme!.hasPrefix("fb\(fbSDKAppId)"),
            url.host == "authorize" { // facebook
            return FBSDKApplicationDelegate.sharedInstance().application(application,
                                                                         open: url,
                                                                         sourceApplication: sourceApplication,
                                                                         annotation: annotation)
}
10
задан Lightness Races with Monica 9 February 2012 в 11:05
поделиться

8 ответов

Основной дефект 391 объясняет проблему.

По сути, текущий стандарт C ++ требует, чтобы конструктор копирования был доступен при передаче временного типа класса в ссылку на константу.

] Это требование будет удалено в C ++ 0x.

Логика требования конструктора копирования взята из этого случая:

C f();
const C& r = f(); // a copy is generated for r to refer to
12
ответ дан 3 December 2019 в 16:54
поделиться

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

РЕДАКТИРОВАТЬ: Компилятор Comeau C ++ сообщает следующее:

Comeau C/C++ 4.3.10.1 (Oct  6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing.  All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 38: error: "A::A(const A &)" (declared at line 17), required
          for copy that was eliminated, is inaccessible
    A a(foo(A(10)));    // This is line 38
            ^

1 error detected in the compilation of "ComeauTest.c".

Обратите внимание, что если включены расширения C ++ 0x, он отлично компилируется в компиляторе Comeau C ++.

1
ответ дан 3 December 2019 в 16:54
поделиться

As far I see you are not using the copy constructor anywhere. In the statement foo(A(10)) you are creating a temporary object of class A and passing it as a const-reference to foo. The foo returns an integer which is used in the construction of object a. Hence I don't see where the copy constructor is getting involved here and how NRVO comes into picture. Also, I compiled the following code by making the copy constructor private and it compiled fine in VS2008.

using namespace std;

class A
{
 public:
  A(const int n_);
 private:
  A(const A& that_);
  A& operator=(const A& that_);
};

A::A(const int n_)
{ cout << "A::A(int), n_=" << n_ << endl; }

A::A(const A& that_)    // This is line 21
{ cout << "A::A(const A&)" << endl; }

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

int foo(const A& a_)
{ return 20; }


int main(int argc,char *argv[])
{
   A a(foo(A(10)));    // This is line 38
  return 0;

}   
3
ответ дан 3 December 2019 в 16:54
поделиться

Еще одно замечание: компилятор делает другое при работе с временным . Так что речь идет не о конструкторе копирования, а о промежуточном временном.

A original(10);
foo( original ); // does compile
foo( A(10) ); // doesn't compile - needs a copy constructor
2
ответ дан 3 December 2019 в 16:54
поделиться

Стандарт 2003 года в §12.2 / 1 гласит:

Даже если создание временный объект избегается (12.8), все смысловые ограничения должны быть уважаемый как будто временный объект был создан. [Пример: даже если конструктор копирования не вызывается, все семантические ограничения, такие как доступность (пункт 11), должна быть доволен. ]

Подобные примеры есть. Насколько я понимаю, компилятор может создавать временные библиотеки или оптимизировать их.

5
ответ дан 3 December 2019 в 16:54
поделиться

В выражении:

A a(foo(A(10)));

Результатом подвыражения A (10) является rvalue типа A . (5.2.3 [expr.type.conv])

При инициализации константной ссылки из rvalue компилятор может создать временную ссылку из rvalue и привязать ее к ссылке . Даже если он этого не сделает, конструктор копирования должен быть доступен. (8.5.3 [decl.init.ref]) Этого не было бы, если бы ссылка была инициализирована из совместимого со ссылками lvalue , где требуется прямая привязка.

Как foo принимает свой параметр по ссылке, а не по значению, для самой инициализации аргумента не требуется копии.

foo возвращает int, поэтому нет копии A Вот.

1
ответ дан 3 December 2019 в 16:54
поделиться

В общем, вы не должны беспокоиться о том, когда и когда вызывается конструктор копирования. Стандарт C ++ довольно расслаблен в отношении того, когда вызовы конструктора копирования будут удалены или, если на то пошло, добавлены. Если вашему классу это необходимо по логике, предоставьте его (и не забудьте о деструкторе и операторе присваивания) - это разумное правило.

0
ответ дан 3 December 2019 в 16:54
поделиться

При вызове:

foo( A(10) );

временный объект создается в течение времени существования вызова. Конструктор копирования используется для заполнения данных. Временный объект удаляется после выполнения вызова.

При вызове:

{ 
  A original(10);
  foo( original ); 
}

Оригинал удаляется после выхода из блока. Его можно безопасно использовать в качестве параметра.

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

0
ответ дан 3 December 2019 в 16:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: