Могло бы быть слишком старым, но здесь мое решение для быстрого
class Recursion {
func fibonacci(_ input: Int) {
var dictioner: [Int: Int] = [:]
dictioner[0] = 0
dictioner[1] = 1
print(fibonacciCal(input, dictioner: &dictioner))
}
func fibonacciCal(_ input: Int, dictioner: inout [Int: Int]) -> Int {
if let va = dictioner[input]{
return va
} else {
let firstPart = fibonacciCal(input-1, dictioner: &dictioner)
let secondPart = fibonacciCal(input-2, dictioner: &dictioner)
if dictioner[input] == nil {
dictioner[input] = firstPart+secondPart
}
return firstPart+secondPart
}
}
}
// 0,1,1,2,3,5,8
class TestRecursion {
func testRecursion () {
let t = Recursion()
t.fibonacci(3)
}
}
Вы правильно процитировали стандарт. Позвольте мне подчеркнуть:
имя , объявленное в блоке, является локальным для этого блока. Его потенциальная область действия начинается в точке объявления и заканчивается в конце декларативной области.
Фактически, вы не объявляли никакого имени . Ваша строка
MyClass (12345);
даже не содержит объявления ! Он содержит выражение, которое создает экземпляр MyClass, вычисляет выражение (однако в данном конкретном случае вычислять нечего), приводит его результат в void
и уничтожает созданные там объекты.
Менее запутанная вещь будет звучать так, как будто
call_a_function(MyClass(12345));
Вы видели это много раз и знаете, как это работает, не так ли?
Объект, созданный в вашем
MyClass(12345);
, является временным объектом, который является живым только в этом выражении ;
MyClass m(12345);
- это объект, который активен для всего блока.
Фактически вы создаете объект, не сохраняя его в области видимости, поэтому он уничтожается сразу после создания. Отсюда и такое поведение.
Вы не можете получить доступ к созданному объекту, так зачем компилятору хранить его?
Чтобы ответить на другие ваши вопросы. Ниже приводится вызов оператора запятой. Он создает временный MyClass
, который включает вызов его конструктора. Затем он вычисляет второе выражение cout << "Y" << endl
, которое выводит Y. Затем, в конце полного выражения, он уничтожает временное, которое вызывает его деструктор. Итак, ваши ожидания оправдались.
MyClass (12345), cout << "Y" << endl;
Чтобы следующее работало, вы должны добавить круглые скобки, потому что запятая имеет предопределенное значение в объявлениях. Он начнет объявлять функцию some_func
, возвращающую int
и не принимая никаких параметров, и назначит объект scoped_lock
для x
. Используя круглые скобки, вместо этого вы говорите, что все это представляет собой одно выражение оператора запятой.
int x = (boost::scoped_lock (my_mutex), some_func()); // still multi-thread safe
Следует отметить, что следующие две строки эквивалентны. Первый не создает временный безымянный объект с использованием my_mutex
в качестве аргумента конструктора, но вместо этого круглые скобки вокруг имени являются избыточными. Не позволяйте синтаксису вводить вас в заблуждение.
boost::scoped_lock(my_mutex);
boost::scoped_lock my_mutex;
Я видел неправильное использование терминов «область действия» и «время жизни».
Область
- это место, где вы можете ссылаться на имя, не уточняя его. Имена имеют области действия, а объекты наследуют область действия имени, используемого для их определения (таким образом, иногда в Стандарте говорится «локальный объект»). Временный объект не имеет области видимости, потому что у него нет имени. Точно так же объект, созданный new
, не имеет области действия. Область видимости - это свойство времени компиляции. Этот термин часто неправильно используется в Стандарте, см. этот отчет о дефектах , поэтому довольно сложно найти реальное значение.
Время жизни
- это свойство времени выполнения. То есть, когда объект настроен и готов к эксплуатации. Для объекта типа класса время жизни начинается, когда конструктор завершает выполнение, и заканчивается, когда деструктор начинает выполнение. Срок службы часто путают со сферой действия, хотя это совершенно разные вещи.
Срок службы временных конструкций точно определен. У большинства из них заканчивается срок службы после оценки полного выражения, в котором они содержатся (например, оператора запятой выше или выражения присваивания). Временные объекты могут быть привязаны к константным ссылкам, что продлит их срок службы. Объекты, которые выбрасываются в исключения, также являются временными, и их жизнь заканчивается, когда для них больше нет обработчика.