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)
}
Основной дефект 391 объясняет проблему.
По сути, текущий стандарт C ++ требует, чтобы конструктор копирования был доступен при передаче временного типа класса в ссылку на константу.
] Это требование будет удалено в C ++ 0x.
Логика требования конструктора копирования взята из этого случая:
C f();
const C& r = f(); // a copy is generated for r to refer to
Конструктор копирования не используется, но для того, чтобы код для компиляции был доступен конструктор копирования.
РЕДАКТИРОВАТЬ: Компилятор 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 ++.
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;
}
Еще одно замечание: компилятор делает другое при работе с временным . Так что речь идет не о конструкторе копирования, а о промежуточном временном.
A original(10);
foo( original ); // does compile
foo( A(10) ); // doesn't compile - needs a copy constructor
Стандарт 2003 года в §12.2 / 1 гласит:
Даже если создание временный объект избегается (12.8), все смысловые ограничения должны быть уважаемый как будто временный объект был создан. [Пример: даже если конструктор копирования не вызывается, все семантические ограничения, такие как доступность (пункт 11), должна быть доволен. ]
Подобные примеры есть. Насколько я понимаю, компилятор может создавать временные библиотеки или оптимизировать их.
В выражении:
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
Вот.
В общем, вы не должны беспокоиться о том, когда и когда вызывается конструктор копирования. Стандарт C ++ довольно расслаблен в отношении того, когда вызовы конструктора копирования будут удалены или, если на то пошло, добавлены. Если вашему классу это необходимо по логике, предоставьте его (и не забудьте о деструкторе и операторе присваивания) - это разумное правило.
При вызове:
foo( A(10) );
временный объект создается в течение времени существования вызова. Конструктор копирования используется для заполнения данных. Временный объект удаляется после выполнения вызова.
При вызове:
{
A original(10);
foo( original );
}
Оригинал удаляется после выхода из блока. Его можно безопасно использовать в качестве параметра.
Для оптимальной скорости передайте объект по ссылке, используя временную переменную, которая будет отброшена компилятором во время его оптимизации.