澄清:是什么让'new'成为C ++中的运算符

时间:2014-09-15 13:33:03

标签: c++ new-operator

我实际上来自Java方面,因此在学习C ++方面有点困惑。

我看到的一件事是许多教程将new描述为运算符。在Java中,我通常使用该关键字来实例化类,即从类中创建对象。

MyObject mo = new MyObject();

我知道它也可以像int* a = new int;一样用于分配动态内存,但是,我不知道为什么这被称为运算符。我认为运算符是用于执行数学运算的符号,也就是操作数之间的运算符。但是,根据我的基本理解,在操作数之间不使用new。

任何人都可以澄清为什么这被称为运营商?

感谢。

5 个答案:

答案 0 :(得分:4)

  

我认为运算符是用于执行数学运算的符号,也就是操作数之间的运算符

仅对二进制中缀运算符也是如此。还有一元运算符在C ++中采用单个操作数(数字否定;逻辑否定),带括号的后缀运算符(方括号,括号)和带括号的前缀运算符(转换)。

考虑到C ++中的这么多运算符,new也是运算符也就不足为奇了。它是一个前缀关键字运算符,它对类型名称进行操作,并生成指向该类型实例的指针。运算符也有多种形式:除了常规new之外,还有一个展示位置new运算符,其语法略有不同。

答案 1 :(得分:1)

由于C ++中基元和对象之间的区别,"运算符"有两个含义。第一个含义接近于您在问题中描述的内容:运算符对其原始参数执行某些特定操作,如标准定义的添加或内存分配。

但是当与对象一起使用时,运算符的工作方式完全不同:它们调用类的相应成员函数。例如,对基元进行布尔否定的!调用对象的bool operator !()函数。 C ++中的文件流重新定义!函数以测试流中是否发生错误。

new是一个运营商,因为它同样calls a member function(并且可以重新定义!虽然我从未见过有人这样做过。)

答案 2 :(得分:1)

Java和C ++中new的语义实际上非常相似。在这两种语言中,如

之类的陈述
Object o = new Object();  // Java

Object * optr = new Object();  // C++
  • 分配内存(在免费商店中)足够大以容纳Object
  • 类型的对象
  • 调用Object的构造函数,将指向新分配的内存的指针作为this指针传递给它。

在Java中,你背后会发生一些更多的魔法,但现在让我们把它放在一边。

内置类型的语义(Java中的原语)也没有太大的不同。

在Java中

int[] array = new int[42];

分配足够大的内存以容纳42 int并用0初始化它们。

在C ++中

int * array = new int[42];  // not value-initialized

还分配(在免费商店上)连续内存,其大小足以容纳42 int但不初始化它们。如果你想要值初始化,请明确说明:

int * array = new int[42]();  // initialized to 0

最大的不同可能是这些运营商的使用方式。在Java中,如果我们想要一个新对象,我们就没有机会调用(可能是通过工厂方法的一些间接)new。在C ++中,我们不仅可以在免费存储(堆)上创建对象,还可以使用所谓的自动存储持续时间(即将它们压入堆栈)。在Java中,这只能用于原始类型。

int i = 7;  // valid in both languages
std::string name("Mona Lisa");  // valid C++, invalid Java

通常,这是你应该在C ++中做的事情。程序员习惯于使用Java并学习C ++以便在真正不需要的地方使用new,这是一个常见的错误。

最后,由于C ++默认没有垃圾收集器,如果你从免费商店分配内存(使用运算符new),你必须在需要时再次释放它(使用运算符delete)它不再。

为什么newdelete被称为运营商?我不知道。真的有关系吗?我认为这是有道理的,特别是因为您可以像操作符+-一样重载它们。

C ++中的对象创建语法曾经有点混乱。所有这些(有时)都是有效的,但看起来完全不同:

// automatic storage
int a = 7;
std::string name;  // default constructor
std::string name("Mona Lisa");
// free store (bad idea in this case)
std::string * nameptr = new std::string();  // default constructor
std::string * nameptr = new std::string("Mona Lisa");

关于哪些符号在哪种情况下有效,有许多规则,如果你忘了,可能会发生一些奇怪的惊喜。

从C ++ 11开始,我们使用初始化列表创建了一个统一的对象创建语法:

// automatic storage
int a {7};
std::string name {}  // default constructor
std::string name {"Mona Lisa"};
// free store (bad idea in this case)
std::string * nameptr = new std::string {};  // default constructor
std::string * nameptr = new std::string {"Mona Lisa"};

不幸的是,由于旧的语法仍然有效,我们现在有更多的选择。

答案 3 :(得分:0)

成为运营商意味着什么?在编程语言中,operators是一种行为类似于函数但在语义上或语法上与正常函数不同的构造。

在C ++中,运算符在语义上是特殊的,因为它们可以重载并且它们的参数必须符合特定的要求。显然他们的语法也很特殊。

new符合所有这些要求。

答案 4 :(得分:0)

C ++不是Java。在Java中,运算符不能重载。

在C ++中,他们可以并且有一种语法可以做到这一点。要在C ++中重载new,请在其前使用单词operator。还有operator new[]可以重载。

我认为它使它脱颖而出不是一个函数,即使它看起来像一个函数,即它需要一个大小的参数并返回void *。

您也可以重载班级成员newdelete以及new[]delete[]。 (对于一个类来说,奇怪的是operator new仍然将一些字节作为参数,这看起来很奇怪,因为它必须是类的大小,所以你可能认为它可能是隐含的。)