【问题标题】:Initializing an object with and without new operator使用和不使用 new 运算符初始化对象
【发布时间】:2011-11-23 08:14:11
【问题描述】:

如果我有课Rectangle

class Rectangle{

private:
    double width;
    double height;


public:
void    Set(double w , double l){
    width   = w;
    height  = l;
}
};

然后我取消了这样一个对象:

Rectangle *Obj;

然后尝试初始化它的属性:

Obj->Set(3,5);

编译器在运行时显示:The variable 'Obj' is being used without being initialized.

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

Rectangle *Obj=new Rectangle;

我想问一下原因!为什么编译器在编译时没有显示任何错误?

【问题讨论】:

    标签: c++ memory-management new-operator


    【解决方案1】:
    Rectangle *Obj;
    

    只定义一个 指针 指向 Rectangle 类的对象。定义一个指针不会为对象本身保留任何内存,只是为指针保留。因此,如果您访问该指针,您可能最终会到达内存中甚至不属于您的进程的地址。但是,编译器无法知道您没有初始化指针(这里的关键字是别名),因此无法输出错误消息。

    解决方案是像您建议的那样使用new,或者像这样声明Rectangle 的实例:

    Rectangle Obj;
    

    这将调用一个默认构造函数。然后,您可以使用

    设置您的成员
    Obj.Set(3, 5);
    

    【讨论】:

    • 只是个傻瓜,但Rectangle* Obj; 不只是声明;它也定义。它确实保留了内存;足够的内存来存储一个指针。
    • @JamesKanze:你当然是对的。我会马上更新我的答案
    【解决方案2】:

    然后我取消了这样一个对象:

    Rectangle *Obj;
    

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

    【讨论】:

    • 指针是一个对象,至少在 C++ 中是这样。这定义了一个类型为Rectangle* 的对象。当然是未初始化的。
    【解决方案3】:

    嗯,有点混乱:

    编译器在运行时显示:变量 '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);
    
    //
    

    虽然无论何时使用new,您也应该记住delete。这可能是一场噩梦(也有例外)。我建议:

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

    【讨论】:

    • 最简单(也是最好)的方法不是:Rectangle Obj = { 3, 5 };。作为一般规则,您不应创建未初始化的对象。 (唯一的例外可能是您正在阅读它,在下一条语句中使用&gt;&gt;。)
    • @JamesKanze: Rectangle Obj 不会创建未初始化的对象(至少我不认为它是一个没有默认构造函数和字段初始化器的结构。另外,我倾向于不抛出 C ++11 初学者答案中的细节;shared_ptr 可以从 boost 中使用,统一初始化不能。(PS widthheight 无论如何都是私有的)
    • 这与他对Rectangle 的实现有关。我错过了private;无法创建初始化的Rectangle。他需要一个构造函数,而不是Set 函数。
    • @JamesKanze:我非常同意那个。这个问题也有点离题:)
    【解决方案4】:

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

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

    • 我们什么时候释放Obj
    • 谁释放Obj
    • 在堆上创建Rectangle 对性能有何影响?
    • 在这个环境中,我们是否有足够的资源(内存、CPU 等)来创建矩形,尤其是在它很大的情况下。
    • 您是否将Obj 的地址传递到某处,然后通过一些我们无法静态分析的复杂方法在运行时实例化它?

    您所做的不是语法错误,而是编译器在编译时抛出的错误——错误。分析器(内置于 Visual Studio 2010 专业版中)可能会警告您正在使用未初始化的变量,尽管这是可选的,您可能需要打开它。

    【讨论】:

      【解决方案5】:

      没有 new 的指针是在声明没有记忆的东西.. 所以你必须使用 new 指针。 然而 矩形矩形; 将默认分配内存。

      检查这个, 在 Rectangle 类中创建一个构造函数,例如,

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

      然后,在主要

      Rectangle *rect; -->>O/P  -- "Nothing"
      Rectangle rect2; -->>O/P  -- Rectangle Constructor
      rect=new Rectangle; -->>O/P  -- Rectangle Constructor
      

      【讨论】:

        【解决方案6】:

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

        因为,它语法正确。但是,这样的语句会导致未定义的行为,智能编译器总会发出警告。

        在 g++ 中,您可以将此类编译器警告转为错误。

        【讨论】:

          【解决方案7】:

          语句矩形*obj 只是表示存在一个指针,它将指向矩形类型的变量。

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

          两种方式都是通过

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

          rectangle r;
          obj =&r;     //variable is created in the heap storage
          

          【讨论】:

          • 我认为是相反的。 new 的一个在堆上创建,第二个在堆栈中。
          猜你喜欢
          • 2012-03-25
          • 2017-03-31
          • 2017-05-13
          • 2016-07-27
          • 2011-10-30
          • 2011-01-13
          • 2013-06-27
          • 2018-05-07
          相关资源
          最近更新 更多