В вашем примере не выполняется вложенное расширение жизни
В конструкторе
B (const A & amp; a_): a ( a_) {std :: cout & lt; "B ()" & lt; станд :: епсИ; }
Здесь a _
(переименованный для изложения) не является временным. Является ли выражение временным синтаксическим свойством выражения, а id-выражение никогда не является временным. Таким образом, здесь не существует расширения продолжительности жизни.
Вот случай, когда произойдет расширение продолжительности жизни:
B (): a (A ()) {std :: cout & lt ; & Lt; "B ()" & lt; станд :: епсИ; }
Однако, поскольку ссылка инициализируется в ctor-инициализаторе, время жизни продолжается только до конца функции. Per [class.temporary] p5:
Временная привязка к ссылочному элементу в конструкторе ctor-initializer (12.6.2) сохраняется до выхода конструктора. [ ! d35] blockquote>
В вызове конструктора
B b ((A ())); // нужны дополнительные скобки!
Здесь являются , связывающими ссылку на временную. [class.temporary] p5 говорит:
Временная привязка к ссылочному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.
blockquote>Поэтому временный файл
A
уничтожается в конце инструкции. Это происходит до того, как переменнаяB
будет уничтожена в конце блока, объясняя ваш выход в журнал.Другие случаи выполняют вложенное расширение продолжительности жизни
Агрегатная инициализация переменных
Агрегатная инициализация структуры с помощью элемента-ссылки может продлить жизнь:
struct X {const A & amp; a; }; X x = {A ()};
В этом случае временное время
A
привязано непосредственно к ссылке, поэтому временное продление на всю жизнь доxa
, что совпадает с временем жизниx
.Агрегировать временную инициализацию
В C ++ 11 вы можете использовать агрегатную инициализацию для инициализировать временное и, следовательно, получить рекурсивное расширение продолжительности жизни:
struct A {A () {std :: cout & lt; "A ()" & lt; станд :: епсИ; } ~ A () {std :: cout & lt; "~ A ()" & lt; станд :: епсИ; }}; struct B {const A & amp; a; ~ B () {std :: cout & lt; "~ B ()" & lt; станд :: епсИ; }}; int main () {const B & amp; b = B {A ()}; std :: cout & lt; "-----" & lt; станд :: епсИ; }
С помощью соединительной линии Clang или g ++ это производит следующий вывод:
A () ----- ~ B () ~ A ()
Обратите внимание, что временные расширения
A
временно иB
временно продлены. Поскольку сначала выполняется временная постройкаA
, она уничтожается последним.В
std :: initializer_list & lt; T & gt;
инициализацияC ++ 11
std :: initializer_list & lt; T & gt;
выполняет расширение продолжительности жизни, как если бы он привязывал ссылку к базовому массиву. Поэтому мы можем выполнить вложенное расширение продолжительности жизни, используяstd :: initializer_list
. Однако ошибки в компиляторе распространены в этой области:struct C {std :: initializer_list & lt; B & gt; б; ~ C () {std :: cout & lt; "~ C ()" & lt; станд :: епсИ; }}; int main () {const C & amp; c = C {{{A ()}, {A ()}}}; std :: cout & lt; "-----" & lt; станд :: епсИ; }
Производится с стволом Clang:
A () A () ----- ~ C () ~ B () ~ B () ~ A () ~ A ()
и с g ++ trunk:
A () A () ~ A () ~ A () - --- ~ C () ~ B () ~ B ()
Это оба неправильно; правильный выход:
A () A () ----- ~ C () ~ B () ~ A () ~ B () ~ A ()
Найденный сам, оставит вопрос открытым, если кто-то ищет
override class func load() {
NSLog("sdfsdf");
}
EDIT:
Начиная с Swift 1.2 вы больше не можете переопределять load
метод. Посмотрите на метод initialize
вместо этого, он ведет себя иначе, чем нагрузка, хотя он получил имя при первом обращении к классу, а не по начальной загрузке приложения
в Swift 2.0, используйте этот метод
public override class func initialize()
@objc
.
– devios1
3 March 2016 в 22:25
Поддержка переопределения нагрузки была удалена в Swift 1.2
Хотя прямой стимул недоступен для Swift, это может быть достигнуто относительно элегантно с Objective-C и категориями. MyClass
должен по-прежнему наследоваться от NSObject
и иметь метод class / static swiftyLoad
, который вызывается из Objective-C в MyClass.m
, который вы включаете в источники компиляции рядом с MyClass.swift
:
# MyClass.swift
import Foundation
public class MyClass: NSObject
{
@objc public static func swiftyLoad() {
Swift.print("Rock 'n' roll!")
}
}
# MyClass.m
#import "MyProject-Swift.h"
@implementation MyClass (private)
+ (void)load { [self swiftyLoad]; }
@end
] . Лучшая часть не нужно возиться с перемычками заголовков или чем-нибудь еще, она просто работает. Есть несколько исправлений, особенно при использовании этого подхода в статических библиотеках, ознакомьтесь с полным сообщением на Medium для деталей! ✌️
Для Swift 2 или 3 (т. е. post-Swift 1.2) вы можете использовать:
class MySwiftClass: NSObject {
internal override class func initialize() {
DoStuff()
super.initialize()
}
}
Но, как вы можете видеть, ваш класс должен наследовать (прямо или косвенно) форму NSObject. Это необходимо, потому что initialize()
вызывается средой выполнения ObjC.
И метод initialize()
вызывается только при ссылке MySwiftClass
. Так что это не будет так магии, как load()
.
Но это также будет более безопасным. Например: включая фреймворк (скажем, просто добавив его к вашему Podfile
), не позволит таинственным образом начать вести себя, как только ваше приложение запустится, без необходимости добавлять одну строку кода к вашему project ( хотя бы ... Надеюсь!
NSObject
. – Jack Lawrence 23 July 2014 в 02:28@objc
; не обязательно спускаться сNSObject
. – newacct 23 July 2014 в 03:02override
). – Jack Lawrence 23 July 2014 в 03:21import Foundation @objc class MyClass { class func load() { println("sdfsdf") } }
– newacct 23 July 2014 в 03:44internal override class func initialize() { }
для подкласса NSObject. Я не нашел, чтобыinitialize()
разрешался в чистом объекте Swift. – l --marc l 21 November 2015 в 07:28