如果在没有 new 运算符的情况下初始化,C++是否将类对象视为值类型

Does C++ treat Class Objects like value types if initialized without the new operator?

本文关键字:是否 对象 类型 C++ new 运算符 初始化 情况下 如果      更新时间:2023-10-16

示例代码:

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 是引用类型,最后 2 行应该是 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 */
基本上

是的(如果你认为C++等同于Java的意思

)。

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

当您执行a=b时,您不会将一个对象与另一个对象一起引用,但在这种情况下,执行成员赋值。这基本上就像说

a.someNumber = b.someNumber;

它不被视为值类型,事实上它是。

在 Java 中,对象

变量存储对对象的引用,而在C++中,对象与其引用之间存在重要差异。默认情况下,赋值实际上是按值分配的。

如果希望变量只是引用,则可以使用引用或指针类型,具体取决于您希望使用它的内容。这些类型声明为 T*T&

为了进一步说明这一点:

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

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

在C++对象在没有指针引用的情况下创建时,它们被称为静态(堆栈)变量。 动态(堆)变量是需要手动内存管理的指针引用。

相比之下,在 Java 或 C# 中,几乎所有对象都是引用类型,它们的行为类似于指针,只是它们是垃圾回收的,而值类型是通常不可变的所有对象的特殊子集。 (C++堆栈变量肯定不是不可变的)。

虽然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 )。

简短的解释在这个关键部分

b = a;

您正在使用复制赋值运算符,这意味着此处的符号=

此运算符的默认行为是应用成员副本,因此,如果您不定义/重载自己的运算符,此行将复制存储在a所有成员中的所有值b的相应成员中。

new运算符 这是一个完全不同的故事,它通常用于分配堆上的对象并使用指针管理它们,避免堆栈和不必要的副本。

默认情况下,C++ 将其类视为值类型并创建深层(元素)副本。

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

这个(以及其他一些"技巧")就是为了举例,如何设计shared_ptr智能指针。它是一个C++类,其中每个实例都引用相同的原始数据,无论复制频率如何。