我实际上来自Java方面,因此在学习C ++方面有点困惑。
我看到的一件事是许多教程将new
描述为运算符。在Java中,我通常使用该关键字来实例化类,即从类中创建对象。
MyObject mo = new MyObject();
我知道它也可以像int* a = new int;
一样用于分配动态内存,但是,我不知道为什么这被称为运算符。我认为运算符是用于执行数学运算的符号,也就是操作数之间的运算符。但是,根据我的基本理解,在操作数之间不使用new。
任何人都可以澄清为什么这被称为运营商?
感谢。
答案 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
)它不再。
为什么new
和delete
被称为运营商?我不知道。真的有关系吗?我认为这是有道理的,特别是因为您可以像操作符+
或-
一样重载它们。
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 *。
您也可以重载班级成员new
和delete
以及new[]
和delete[]
。 (对于一个类来说,奇怪的是operator new
仍然将一些字节作为参数,这看起来很奇怪,因为它必须是类的大小,所以你可能认为它可能是隐含的。)