Swift可选inout参数和nil

Swift可选inout参数和nil,swift,optional,Swift,Optional,Swift中的函数是否可以有一个可选的inout参数?我正在尝试这样做: func testFunc( inout optionalParam: MyClass? ) { if optionalParam { ... } } …但当我试图调用它并传递nil时,它给了我一个奇怪的编译错误: Type 'inout MyClass?' does not conform to protocol 'NilLiteralConvertible' 我不明白为什么我的类在声

Swift中的函数是否可以有一个
可选的
inout
参数?我正在尝试这样做:

func testFunc( inout optionalParam: MyClass? ) {
    if optionalParam {
        ...
    }
}
…但当我试图调用它并传递
nil
时,它给了我一个奇怪的编译错误:

Type 'inout MyClass?' does not conform to protocol 'NilLiteralConvertible'

我不明白为什么我的类在声明为可选时必须遵守某些特殊协议。

它不会编译,因为函数需要引用,但您传递了
nil
。这个问题与选择无关

通过使用
inout
声明参数,意味着您将在函数体内部为其赋值。它如何将值赋给
nil

你需要像这样称呼它

var a : MyClass? = nil
testFunc(&a) // value of a can be changed inside the function

如果你知道C++,这是C++代码的版本,没有可选的

struct MyClass {};    
void testFunc(MyClass &p) {}
int main () { testFunc(nullptr); }
您收到了这个错误消息

main.cpp:6:6: note: candidate function not viable: no known conversion from 'nullptr_t' to 'MyClass &' for 1st argument

这相当于你所得到的(但更容易理解)

这是可能的,而且可能与之有关。()

可选项可以具有nil值,但不应为nil。因此,如果您只是不将其传递给函数或传递类型为MyClass的变量,那么这个可选选项就可以工作了?值为零。就像布莱恩州

编写函数时,它必须有一个默认值作为可选参数,如下所示:

func testFunc(inout optionalParam:MyClass?={var nilRef:MyClass?;return &nilRef}()) {
    if optionalParam != nil {
        ...
    }
}
请注意,如果optionalParam{…}
更改为
如果optionalParam!=无{…}

如果optionalParam?!=nil
,作为uwrapping,
optionalParam?
optionalParam==nil
时失败~注意,
var a:MyClass?
在赋值之前的值为nil

调用是,
testFunc(可选参数:&a)
testFunc()
,但决不
testFunc(nil)

我想你可能会把两个不同的概念交织在一起,因为它们有相似的名称、可选参数和可选项。Optionals是具有扩展nil条件的变量。可选参数是可选的功能参数

进一步阅读。苹果正试图将措辞从可选参数改为“带有默认值的参数”。不幸的是,他们没有在这些新的可选内容中包含可选参数行为。如果零个选项在打开时失败,那么将其作为选项传递有什么意义。如果可以在打开包装之前传递,那么它可能会更深入地理解这个可选内容的核心。。。薛定谔猫的确切含义是:

只能将变量作为输入输出参数的参数传递。 不能将常量或文字值作为参数传递,因为 无法修改常量和文字。您可以放置一个符号(&) 当您将变量作为参数传递给 一个inout参数,指示可以由 功能

但是请注意,根据@gnasher的注释(编辑),如果您打算或希望将实例替换为另一个实例,而不仅仅是修改原始实例,则只需将类作为inout(也称为引用)传递。文件中涉及这一点的段落是:

输入输出参数

如上所述,可变参数只能在 函数本身。如果希望函数修改参数的 值,并且您希望这些更改在函数调用后保持不变 结束后,将该参数定义为输入输出参数

这里有三个测试涵盖了var和inout的使用

class Bar : Printable {
    var value = 1

    init(_ value:Int) { self.value = value }
    var description:String { return "Bar is: \(value)" }
}

let bar = Bar(1)
func changeBarWithoutInoutSinceBarIsAClassYaySwift(b:Bar) { b.value = 2 }
changeBarWithoutInoutSinceBarIsAClassYaySwift(bar)
println("after: \(bar)") // 2

var bar2 = Bar(0)
func tryToReplaceLocalBarWithoutInout(var b:Bar) { b = Bar(99) }
tryToReplaceLocalBarWithoutInout(bar2)
println("after: \(bar2)") // 0

var bar3 = Bar(0)
func replaceClassInstanceViaInout(inout b:Bar) { b = Bar(99) }
replaceClassInstanceViaInout(&bar3)
println("after: \(bar3)") // 99

实际上@devios1需要的是“可选指针”。 但是我不在我的班上吗?表示“指向可选项的指针”。 以下内容应适用于Swift 4

class MyClass {
    // func foo() {}
}

func testFunc(_ optionalParam: UnsafeMutablePointer<MyClass>? ) {
    if let optionalParam = optionalParam {
        // optionalParam.pointee.foo()
        // optionalParam.pointee = MyClass()
    }
}

testFunc(nil)

var myClass = MyClass()
testFunc(&myClass)
class-MyClass{
//func foo(){}
}
func testFunc(uOptionalParam:UnsafeMutablePointer?){
如果让optionalParam=optionalParam{
//optionalParam.pointee.foo()
//optionalParam.pointee=MyClass()
}
}
testFunc(无)
var myClass=myClass()
testFunc(&myClass)

所以我猜答案是否定的。我确信这在Objective-C中是可能的。哦,好吧。@chaiguy也许你可以尝试像
自动释放指针那样的指针。但是在我看来,这是丑陋的。@devios在客观条件下肯定是可能的。这就是为什么nils是有毒的。Swift的例子很好,并且使之成为可能。我忘了在try块中提到常见的流行语是
,如果a==nil{a=MyClass();}
,不幸的是,这似乎没有在Swift 3.0中为我在Xcode上编译:我得到错误
“&”只能立即出现在调用参数列表中
,实际上,inout对引用(类)的作用是一样的。除了结构的值之外,结构的所有元素都是引用,而引用的值只是引用本身。如果您传递NSMutableString thisString,则无法将其更改为NSMutableString thatString,除非您使用var或inout。更改字符并不会更改引用。@gnasher,谢谢您的发布,这样更有意义。我相应地更新了我的答案。