如果没有使用new运算符初始化,C++是否会像值类型一样处理类对象?

4

示例代码:

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;

它被视为值类型吗?

------这是我的MyItemType.h文件------------

#ifndef MYITEMTYPE_H
#define MYITEMTYPE_H

class MyItemType{

public:
    int someNumber;
    MyItemType();
};

MyItemType::MyItemType(){
}

#endif  /* MYITEMTYPE_H */

5
除了显式引用以外,C++ 中的所有东西都是值类型。当你将 a 赋值给 b 时,实际上是调用了默认的复制赋值运算符。 - Cory Nelson
1
C++没有值类型和引用类型。如果可以的话,对象上的operator=将执行成员逐一复制。 - chris
6个回答

8

基本上是的(如果你认为C++的等效意味着与Java相同)。

AClassType anInstance; 是一个对象,而不是引用。 MyItemType aMyItemType b 是不同的对象,它们位于不同的内存空间,因此对其中一个对象的更改不会影响另一个对象。

当你执行 a=b 时,你并没有将一个对象引用另一个对象,而是进行了逐成员赋值。这基本上就像说

a.someNumber = b.someNumber;

7

这个值类型并不像在Java中一样被处理成对象,实际上它就是一个对象。

在Java中,对象变量存储的是对象的引用,而在C++中,一个对象和它的引用之间有一个重要的区别。默认情况下,赋值操作实际上是按值进行的。

如果你想要一个变量只是一个引用,你需要使用指针或引用类型,具体取决于你想要做什么。这些类型被声明为T*T&

为了更好地阐述这一点:

在Java中,当你说MyClass obj时,一个对象会被创建,但一个引用/指针会存储在变量obj中。

在C++中,MyClass obj会创建一个对象并将其存储在obj中。如果你想要使用引用/指针,你需要显式地声明变量为MyClass* objPointerMyClass& objReference


4

C++虽然不称呼对象为值类型或引用类型,但是值类型和引用类型的行为在C++中有对应关系。

给定两个对象 aba = b

  1. 值类型将b的内容复制到a中,使它们成为分离的对象;
  2. 引用类型将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

指针/引用可以是值对象,也可以是通过new或其他内存管理方案(例如malloc或Win32的CoTaskMalloc)分配的对象。


4
在C++中,当对象被创建时没有使用指针引用,它们被称为静态(堆栈)变量。动态(堆)变量是需要手动内存管理的指针引用。
相比之下,在Java或C#中,几乎所有对象都是引用类型,它们的行为类似于指针,但它们会被垃圾回收,而值类型是所有对象的一个特殊子集,通常是不可变的。(C++堆栈变量肯定不是不可变的)。

2
这个关键部分的简短解释如下:
b = a;

你正在使用复制赋值运算符,这意味着这里的符号=
该运算符的默认行为是应用成员逐一复制,因此如果您没有定义/重载自己的运算符,则此行将复制a中所有成员存储的所有值到b的相应成员中。
new运算符则完全不同,通常用于在堆上分配对象并使用指针管理它们,避免使用栈和不必要的复制。

0

默认情况下,C++将其类视为值类型并进行深度(逐元素)复制。

但是,您可以将成员变量存储在类内的自由存储区(堆上),并自定义(覆盖)赋值运算符(代码中的b = a)的行为,以显示引用类型的行为。

这(以及其他一些“技巧”)是例如shared_ptr智能指针设计的示例。它是一个C++类,其中每个实例引用相同的原始数据,无论复制多少次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接