Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用和不使用新运算符初始化对象_C++_Memory Management_New Operator - Fatal编程技术网

C++ 使用和不使用新运算符初始化对象

C++ 使用和不使用新运算符初始化对象,c++,memory-management,new-operator,C++,Memory Management,New Operator,如果我有一个类矩形 class Rectangle{ private: double width; double height; public: void Set(double w , double l){ width = w; height = l; } }; 我还澄清了一个物体,比如: Rectangle *Obj; Rectangle *Obj; 然后尝试初始化其属性: Obj->Set(3,5); 编译器在运行时显示:正在使

如果我有一个类
矩形

class Rectangle{

private:
    double width;
    double height;


public:
void    Set(double w , double l){
    width   = w;
    height  = l;
}
};
我还澄清了一个物体,比如:

Rectangle *Obj;
Rectangle *Obj;
然后尝试初始化其属性:

Obj->Set(3,5);
编译器在运行时显示:
正在使用变量“Obj”,但未初始化。

该问题可通过以下方式解决:

Rectangle *Obj=new Rectangle;
我会问原因!为什么编译器在编译时没有显示任何错误

我还澄清了一个物体,比如:

Rectangle *Obj;
Rectangle *Obj;

错误,这声明了一个指针,而不是一个对象。必须使用
new
或通过为指针分配现有对象的地址来初始化指针。

Mmm这里有点混乱:

编译器在运行时显示:正在使用变量“Obj”,但未初始化

这就是所谓的编译时。只是澄清一下行话

此外,最简单的方法是

Rectangle Obj;
Obj.Set(3,5);
除了动态分配或多态容器之外,这对于大多数场景都是足够的:

std::vector<Shape*> v;
v.push_back(new Rectange());
v.back()->Set(3,5);

v.push_back(new Circle());
v.back()->Set(3,5);

//
为什么编译器在编译时不显示任何错误

因为,它在语法上是正确的。但是,此类语句将导致未定义的行为,智能编译器将始终发出警告


在g++中,您可以在出现错误时打开此类编译器警告。

使用
矩形*Obj
,您正在声明一个指向矩形的指针,但您没有告诉Obj它应该指向哪个矩形。您可以稍后将
Obj
设置或实例化为现有的
矩形
,或者仅当您需要时

C++就是要让您精确地控制内存和性能。事实上,这就是为什么在一些嵌入式环境中使用它!自动实例化
Obj
会带来几个“问题”

  • 我们什么时候有空
  • 谁解放了Obj
  • 在堆上创建
    矩形
    对性能的影响如何
  • 在这个环境中,我们有足够的资源(内存、CPU等)来创建矩形,特别是如果矩形很大的话
  • 您是否将
    Obj
    的地址传递到某个地方,然后在运行时通过一些我们无法静态分析的复杂方法对其进行实例化
您所做的不是语法错误,而是编译器在编译时抛出的错误。分析器(一个内置于Visual Studio 2010 professional中)可能会警告您正在使用未初始化的变量,尽管这是可选的,您可能需要打开它

Rectangle *Obj;
只定义一个指向类
矩形
对象的指针。定义指针不会为对象本身保留任何内存,只为指针保留内存。因此,如果您访问指针,您可能会在内存中找到一个甚至不属于您的进程的地址。但是,编译器无法知道您尚未初始化指针(此处的关键字为别名),因此无法输出错误消息

解决方案可以像您建议的那样使用
new
,也可以像这样声明
Rectangle
的一个实例:

Rectangle Obj;
它将调用默认构造函数。然后,您可以使用

Obj.Set(3, 5);

没有new的指针正在声明没有内存的内容。。 所以你必须使用新的指针。 然而 矩形矩形; 将默认分配内存

要检查这一点, 在矩形类中创建一个构造函数,如下所示

void Rectangle
{
  cout<<"Rectangle Constructor";
}

语句rectangle
*obj
只意味着存在一个指针,它将指向rectangle类型的变量

使用此语句,您只需创建一个指针 不是对象矩形的实例 要使用此指针,必须将矩形类型变量的地址存储在指针中

这两种方法是通过

obj=new rectangle;  //variable is created in the stack storage


指针是一个对象,至少在C++中是这样的。这定义了一个类型为
Rectangle*
的对象。当然是未初始化的。只是一个nit,但是
Rectangle*Obj不只是声明;它也定义了。它确实保留了记忆;有足够的内存来存储指针。@JamesKanze:你当然是对的。我会马上更新我的答案,最简单(也是最好)的方法不是:
rectangleobj={3,5}。一般来说,您不应该创建未初始化的对象。(关于唯一的例外可能是,如果您在下一个语句中使用
>
)阅读它。)@JamesKanze:
矩形Obj
不会生成未初始化的对象(至少我不认为它是一个没有默认构造函数和字段初始值设定项的结构。此外,我倾向于在初学者的答案中不使用C++11细节;共享的ptr可以从boost中使用,统一的初始化不能。(PS
width
height
无论如何都是私有的)这与他的
矩形
的实现有关。我错过了
私有
;无法创建初始化的
矩形
。他需要的是构造函数,而不是
函数。@JamesKanze:我完全同意这一点。这个问题也有点离题:)我认为是相反的,有new的是在heap上创建的,第二个是在stack中创建的。
rectangle r;
obj =&r;     //variable is created in the heap storage