“new”运算符总是会调用构造函数吗?

7
我的问题受到Thomas Cormen教授在他的Quora回答中第二条评论的影响。他说构造函数执行以下三个任务:
1. 为对象分配内存。 2. 初始化对象的实例变量,例如通过Python中的init隐式调用。(我还强调init方法应该初始化所有实例变量,而不是一些。) 3. 返回对(即地址)对象的引用。
然而,C++的MSDN文档表示,是new运算符完成了这个过程:
从自由存储器中为类型名称为对象或对象数组分配内存,并返回适当类型的非零指针以指向该对象。

我的问题是,谁是对的?或者,也许像帖子上的评论所建议的那样,new运算符总是调用构造函数,这其中是否还有其他更深层次的原因?

谢谢。

$不幸的是,Quora没有复制评论链接的选项 - 我只能复制回答的链接。
*虽然我说的是C ++,但我认为其他语言如Java和C#也是如此(不过我不确定)。


3
我觉得我没有看到你期望分享的第一个链接里的内容。 - François Andrieux
1
也许这两段文字在谈论 new 关键字的不同用法。有 operator newnew expressionsoperator new 分配内存,不调用构造函数并且可以被重载,new expressions(通常)使用 operator new 分配内存并调用构造函数。 - François Andrieux
在MSDN文章中进一步说明:“当使用new为C++类对象分配内存时,内存分配后会调用对象的构造函数。” - Drew Dormann
1
@P.K. 那段文字的上下文似乎很重要,但是我无法使用提供的链接找到您引用的内容。 - François Andrieux
1
可能是Differences Between Python and C++ Constructors的重复问题。 - Sean Munson
显示剩余8条评论
3个回答

5
如果您在链接的MSDN页面上搜索构造函数,它会说:

当使用new为C++类对象分配内存时,对象的构造函数在分配内存后被调用。

换句话说,如果存在构造函数,则会调用构造函数。如果不存在,则不会调用任何构造函数。

抱歉,这让我感到困惑。如果没有定义构造函数,那么按照Cormen的说法,谁(或什么)将执行这三个任务? - P.K.
1
一个类类型的构造函数总是会被调用并且必须存在,否则使用 new 将会是不合法的。尽管如此,该构造函数可以为空并且隐式生成。 - François Andrieux
1
关于“如果不存在”的澄清:默认构造函数是存在的。 - Ripi2
@Ripi2 默认构造函数可能不存在(例如 struct foo { foo() = delete; };),但必须存在一个与 new 提供的参数匹配的构造函数。 - François Andrieux
2
@P.K. 构造函数只能在内存被分配后才能调用。从概念上讲,它不负责分配该内存。是该类的 new operatornew expression 调用来分配内存。 - François Andrieux
显示剩余6条评论

3

如果有疑问,请阅读规范。引自en.cppreference.com

new表达式尝试分配存储空间,然后尝试构造和初始化一个未命名的单个对象或在分配的存储空间中的无名数组中的对象。 new表达式返回对构造对象的prvalue指针,或者如果构造了对象数组,则返回指向数组初始元素的指针。


1
构造函数不分配内存。 new操作符会分配内存,然后调用适当的构造函数。
半伪代码如下:
template <typename T>
T* new(Args... arguments_to_constructor_of_T_if_any)
{
    void* mem = malloc(sizeof(T)); // Allocate memory 

    // Call constructor 
    // Compiler will produce machine code to construct object T over memory mem.
    (mem) T(arguments_to_constructor_of_T_if_any); 

    return (T*)(mem);
}

一个例子:

class A
{
   int a;
   int b;

   A(int a, int b) { this->a = a; this->b = b; };
}

int main() 
{
   A* a = new A(3, 4);

   // After compiled, code above will look like : 
   void* mem = malloc(sizeof(A));

   // Below is A(int, int) constructor
   ((T*) mem)-> a = 3;
   ((T*) mem)-> b = 4;
}

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