C ++中新运算符的返回类型是什么?为什么我们可以将返回值分配给变量(非指针)?
what is the return type of the new operator in c++ & why can we assign the returned value to a variable(non-pointer)?
我知道 c++ 中的 new 运算符总是返回指向所创建对象的指针。
class Node {
int data;
Node* next;
public:
Node();//default
Node(int);//parameter
Node(int, Node*);//parameter2
Node(Node*);//copy
~Node();
void setData(int);
void setNext(Node*);
int getData();
Node* getNext();
void display();
};
这样我们就可以做到:
Node *n = new Node;
但是,我也看到了以下代码:
Node n2 = new Node;
我自己测试了它,我也工作。
这是什么原因呢?
Node(Node*);//copy
这不是复制构造函数,而是从 Node* 到 Node 的隐式转换。
复制构造函数的正确原型是:
Node(Node const&);
对于那些喜欢对编码风格感到愤怒的人来说,这也是一回事:
Node(const Node&);
如果您需要复制构造函数,则很可能还需要赋值运算符:
Node& operator=(Node const&);
如果构造函数接受相同类型的指针,则使该构造函数显式化要安全得多:
explicit Node(Node*);
这会在编译时将赋值从指针捕获到值类型,并可能防止随后的内存泄漏。
Node(Node*);//copy
不是一个正确的复制构造函数。普通的复制构造函数通过常量引用来获取参数,即 Node(Node const& src)
.
尽管如此,`Node(Node*)
仍然存在,当您使用 new Node
中的Node*
初始化Node n2
时,它是选择的构造函数。这是完美的搭配。
如果您正在使用new
和原始指针(即不是std::unique_ptr<Node>
(,请注意内存泄漏。当然,您的公共接口不应该暴露Node*
。
它可能只是因为你创建了一个非常不寻常的复制构造函数:
Node(Node*); //copy
它接受一个指针并从中创建一个对象。因此,您的生产线
Node n2 = new Node;
其实是:
Node n2 = Node( new Node() );
观察返回指针的"新节点",以及对象构造函数Node()
。我认为复制构造函数需要隐式,但那是另一种情况。
这是一个不寻常的复制 ctor,因为复制 ctor 通常不带指针,他们这样做正是出于这个原因:它很容易犯愚蠢的错误和拼写错误,比如在类型后忘记*
。通常,它们对复制的对象进行常量引用:
Node(Node const&); //copy
这样,这条线
Node n2 = new Node;
不会编译,因为无法将Node*
"转换"为Node
。另一方面,如果你真的想让那行再次工作,你需要写:
Node n2 = *(new Node);
或类似的东西。尽管如此,这仍然是一个坏主意,因为最近new
的 -ed 对象永远不会被删除,并且会永远留在内存中(也就是说,直到程序存在(。
要清理它:
Node* tmp = new Node;
Node n2 = Node(*tmp);
delete tmp;
但无论如何,这都接近于废话,因为您创建一个新的 obejct 只是为了创建一个新对象。这个可怕的事情可能应该改写成简单:
Node n2 = Node();
编辑:这当然与普通相同
Node n2;
除非你的编译器是真正的问题:)
你有一个错误的复制构造函数:
Node(Node*);//copy
这实际上是从Node*
到Node
的隐式转换,绝对不是你想要的。根据定义,复制构造函数应允许在参数中const Node&
,例如:
Node( const Node& );
请参阅复制构造函数、赋值运算符和异常安全赋值:
请注意,以下构造函数都不是,尽管事实上 他们可以做与复制构造函数相同的事情,是复制 构造 函数:
MyClass( MyClass* other ); MyClass( const MyClass* other );
这是隐式构造函数转换的情况。
在这种情况下:
Node n = new Node;
将隐式调用Node (Node *);
构造函数。
例如,可以在此处找到更完整的解释。
您可以通过使用 them 显式关键字标记此构造函数来防止这种情况发生:
explicit Node (Node *);
现在上面的代码无法编译(g++ 4.7.2(:
错误:请求从"节点*"转换为非标量类型"节点">
你必须显式调用构造函数:
Node n (new Node);
你的代码之所以有效,是因为你的 Node 类定义了一个采用 Node 指针的构造函数。就是这个:
Node(Node*);//copy
顺便说一下,这不是复制构造函数的正确语法,它将是:
Node(const Node& other);
当您使用 Node n2 = new Node;
将new Node
分配给节点对象时,您将 (1( 在堆上分配一个新的 Node 对象,(2( 通过调用采用 Node 指针的构造函数在堆栈上初始化 n2 和 (3( 泄漏堆分配的节点。
动态内存是使用运算符 new 分配的。
Node *n= new Node;
为 Node
类型的单个元素分配空间,并返回指向该元素的指针。
节点n2=新节点;
由于Node()
和Node(Node*)
功能,在这种情况下工作。
在这种情况下,Node(Node*)
正在执行从Node*
到节点的隐式转换,因为分配正在执行
新建节点 => 节点(新节点( => 节点(节点*(
通过定义合适的构造函数,可以使用几乎任何东西作为构造函数参数来初始化类型的实例。
此外,由于存在从任何原始指针类型到bool
的转换,您还可以执行
bool x = new Node;
并且该语言允许许多其他起初可能看起来令人困惑的内容,例如
Node n = n;
这个想法是,C++程序员更喜欢控制而不是被保姆。因此,在C++中,通常允许未明确禁止的内容,因为在某些情况下,它可能有意义并且有用。其他一些语言基于不同的哲学。
通常(但并非总是(将具有单个参数的构造函数声明为 explicit
是个好主意。那么它就不会被隐式调用。例如,
explicit Node( Node* );
然后声明
Node n = new Node();
将导致编译错误。
但是,显式使用该构造函数,如
Node n( new Node() );
仍将编译。
- 将内存分配返回值强制转换为 TYPE 数组
- 如何删除新分配的字符,这也是函数返回值?
- 当设置对象等于另一个函数的返回值时,为什么要调用移动构造函数/分配
- 获取“将返回值分配给新变量”的警告和输出是内存地址
- 为循环中多次调用的函数返回值预分配内存的正确方法是什么
- 我可以分配成员访问操作员的返回值吗?
- 用户定义功能的返回值的分配:性能
- 分配从upper_bound到reverse_iterator的返回值
- 内存分配,用于在C 11中循环中函数的返回值:如何优化
- 分配操作员返回值类型
- 为什么将boost::move()的返回值分配给非常数引用在C++0x模式下失败,但在C++03模式下有效
- 如果我的C++“新”内存分配失败,如何找出返回值
- 函数在无法分配空间时返回值
- 未分配返回未定义对象类型引用的 C++ 函数的返回值时会发生什么情况
- 当我调用函数而不将其返回值分配给变量时会发生什么
- 如何将实用程序 (grep/sed) 的返回值分配给数组
- C++函数返回值未分配
- C++ Visual Studio Express - 分配返回值失败功能
- 我们不必将函数的返回值分配给变量吗?C/C++
- C ++中新运算符的返回类型是什么?为什么我们可以将返回值分配给变量(非指针)?