示例代码。
MyItemType a;
MyItemType b;
a.someNumber = 5;
b = a;
cout << a.someNumber << endl;
cout << b.someNumber << endl;
b.someNumber = 10;
cout << a.someNumber << endl;
cout << b.someNumber << endl;
输出:
5
5
5
10
如果a和b是引用类型,最后两行应该是10和10 而不是5和10,我想。
这是否意味着当你做这样的声明时。
AClassType anInstance;
就会被当作值类型处理?
#ifndef MYITEMTYPE_H
#define MYITEMTYPE_H
class MyItemType{
public:
int someNumber;
MyItemType();
};
MyItemType::MyItemType(){
}
#endif /* MYITEMTYPE_H */
它并没有被当作一个值类型,事实上它就是一个值类型。
在Java中,对象变量存储的是对对象的引用,而在C++中,对象和它的引用是有重要区别的。赋值在默认情况下确实是按值来的。
如果你想让一个变量只是一个引用,你可以使用引用或指针类型,这取决于你想对它做什么。这些类型被声明为 T*
和 T&
.
再来说明一下。
在Java中,当你说 MyClass obj
对象被创建,但一个引用指针被存储在变量 obj
.
在C++中。MyClass obj
创建对象并将其存储在 obj
. 如果你想使用引用指针,你需要明确地将变量声明为 MyClass* objPointer
或 MyClass& objReference
.
基本上,是的(如果你认为C++的等价物与Java中的意思相同)。
AClassType anInstance;
是一个对象,而不是一个引用。MyItemType a
而 MyItemType b
是不同的对象,它们驻留在不同的内存空间,所以显然对一个对象的改变不会影响另一个。
当你做 a=b
你不会用一个对象来引用另一个对象,但是,在这种情况下,要做一个成员的赋值。这基本上就像说
a.someNumber = b.someNumber;
在C++中,当对象创建时没有指针引用时,称为静态(堆)变量。 动态(堆)变量是指针引用,需要手动管理内存。
相比之下,在Java或C#中,几乎所有的对象都是引用类型,它们的行为与指针类似,只是它们会被垃圾回收,而值类型是所有对象的一个特殊子集,它们通常是不可改变的。 (C++栈变量当然不是不可变的)。
虽然C++没有把对象称为值类型或引用类型,但在C++中,值类型和引用类型的行为具有等价性。
给定两个对象 a
和 b
, a = b
:
b
变成 a
保持它们是独立的对象。b
变成 a
,使它们指向同一个对象。对于C++。
MyClass a; // value type
MyClass b; // value type
MyClass &c = a; // reference type (a reference in C++), fixed to a
MyClass *d = &b; // reference type (a pointer in C++)
a = b; // copy content of b into a
c = b; // copy content of b into a
d = &a; // set d to refer to a
*d = b; // copy content of b into a
Pointersreferences可能是指向value对象, 对象由 new
或其他内存管理方案(如 malloc
或Win32 CoTaskMalloc
).
简单的解释在这个关键部分
b = a;
你使用的是复制赋值运算符,也就是说这个符号在这里。=
.
这个操作符的默认行为是应用成员间的复制,所以如果你没有定义overload你自己的操作符,这条记录将复制所有存储在 a
在相应的成员中 b
.
的 new
操作符就完全不同了,它经常用来在堆上分配对象,用指针管理对象,避免堆和不必要的拷贝。
默认情况下,C++将其类视为值类型,并进行深层(元素方面)复制。
但是你可以将你的成员变量存储在类内部的自由存储中(堆上),并自定义(覆盖)赋值操作符的行为(在你的代码中b = a),以显示引用类型的行为。
这(还有一些其他的 "技巧")是为了举例说明,shared_ptr智能指针是如何设计的。它是一个C++类,每个实例都引用相同的原始数据,不管它被复制的频率如何。