在java和objective-c中,表示对象的变量一般是指向该对象的指针。但是,在 C++ 中,非指针类型保存对象似乎很常见。两者有什么区别?
如果我将一个结构作为参数传递给一个函数,我相信我是按值传递的,这意味着我实际上是在内存中创建一个新的结构,并且在它传递给的函数内部对该结构的更改不会影响函数外部的“源”结构。但是,如果我将一个指针传递给一个结构,仍然只有一个原始结构,并且指针引用的结构的更改将对任何知道该结构的代码可见。我有这个权利吗?
那么,对象有什么区别吗?当我将非指针对象传递给函数时,是否复制了整个对象?
最佳答案
正如你所说。
当您按值传递对象时,将调用其复制构造函数 以生成将在函数内部使用的此类对象的新实例。对此类新对象所做的更改不会反射(reflect)到原始对象1。
与结构一样,默认复制构造函数只是对原始对象进行浅拷贝 - 即,它的字段被复制2 到新实例;在许多情况下,这是不可取的(例如,如果对象包装了一个指针/另一个资源),因此有些类会重新定义复制构造函数或完全禁用它。最后这些类的对象只能通过指针或引用传递。
如果对象大于指针(在大小上),或者通常如果它们的复制构造函数不“便宜”,则按值传递对象的成本可能很高。另一方面,与指针相比,按值传递具有不必指定指针所有权、让被调用者对对象做任何想做的事情等通常的优点。
请注意,按值传递对象会破坏多态性。这是因为按值接收对象的函数接收静态类型对象,具有精确的大小和类型,因此任何传递派生类对象的尝试都将导致对象切片(调用基类的复制构造函数,即默认情况下只复制基类中可用的字段。
这就是为什么传递对象的首选方法通常是通过 const
引用的原因。这产生了几个优点:
- 不涉及拷贝;被调用者将看到的对象将与调用时指定的对象完全相同;
- 由于
const
限定符,不能对原始对象进行任何更改; - 但是,如果被调用者需要更改对象的拷贝,它仍然可以根据引用自己构造一个拷贝;
- 没有笨拙的指针语法;
- 保留了多态性,因为在幕后我们实际上传递了一个指针;
- 对对象所有权没有太大疑问:关于引用的一般规则是它们由调用者拥有。
就对象的“原始字段”而言;当然,如果原始对象和拷贝继续共享指向同一资源的指针/句柄,对其中一个的一些修改可能会影响另一个。
原始类型(以及一般的 POD)按位复制,而非 POD 类型调用复制构造函数。
关于c++ - 在 C++ 中,对象和指向对象的指针有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5372707/