C ++构造函数语法的详细信息

时间:2011-10-16 04:28:31

标签: c++ constructor

这几乎是一个重复的问题,但我真的不明白为另一个问题给出的答案,所以我将再试一次:

我正在学习C ++而我正试图理解创建和使用构造函数的各种选项。所以我的第一个问题是这两个对象创作之间的区别是什么:

 class Example{
      Example(int x){myX = x} ;
      private:
         int myX;
 }

然后在我的主要方法中:

 Example example1 = new Example(5);
 Example example2 = Example(5);
 Example example3(5);

我知道使用new会给我一个动态分配的对象,我稍后需要删除它。并且example2将在堆栈上分配,不需要删除。但我真的不明白何时或为什么要使用example3的构造函数样式。任何涉及最小术语的帮助都会非常感激,因为这就是为什么我似乎无法在别处理解这一点。非常感谢您提供的任何光线,你们可能会为我提供这些。

4 个答案:

答案 0 :(得分:9)

两个声明

Example example2 = Example(5);
Example example3(5);

是等价的。虽然第一个看起来像它可能会创建一个对象,然后调用复制构造函数,但大多数编译器只会创建example2对象。

关于何时选择使用上述哪种款式的决定很大程度上取决于品味。

这是一个完整的示例程序,用于演示:

#include <iostream>

using namespace std;

class Test {
public:
    Test(int x): X(x) {
        cout << "constructor " << X << endl;
    }
    Test(const Test &rhs): X(rhs.X) {
        cout << "copy " << X << endl;
    }
    Test &operator=(const Test &rhs) {
        X = rhs.X;
        cout << "assign " << X << endl;
        return *this;
    }
private:
    int X;
};

int main()
{
    Test t1 = Test(1);
    Test t2(2);
    t2 = t1;
}

和输出(gcc 4.2.1,OS X Lion):

constructor 1
constructor 2
assign 1

注意如何仅为t2 = t1调用赋值运算符(如预期的那样),但根本不调用复制构造函数。 (但是,正如Dennis Zickefoose在评论中指出的那样,复制构造函数必须可访问。尝试在上面的示例中创建复制构造函数private,编译器应该拒绝编译它。)

编辑:请注意,gcc实际上有一个控制此行为的选项:

    -fno-elide-constructors
        The C++ standard allows an implementation to omit creating a
        temporary which is only used to initialize another object of the
        same type.  Specifying this option disables that optimization, and
        forces G++ to call the copy constructor in all cases.

答案 1 :(得分:2)

Example example1 = new Example(5);

由于new Example(5)返回Example上的指针,因此不会编译。正确的用法是Example * example1 = new Example(5)。之后需要删除。

Example example2 = Example(5);

这个创建一个临时的Example实例,并使用(在您的情况下)默认的复制构造函数将其复制到example2。

Example example3(5);

这个在堆栈上创建一个Example实例并调用你的构造函数。

答案 2 :(得分:0)

同时执行

className Object = className(10);
className Object(10);

我相信实际上是等同的。这只是个人偏好。

另一方面,使用new创建对象除了在堆上分配之外,实际上返回指向创建对象的指针。

Example* example1 = new Example(2);

谈到删除,所有这些都将调用相同的类析构函数。

答案 3 :(得分:0)

当你有一个隐式构造函数时,你可以这样做:

class Example{
  public:
  Example(int x = 0):x(myX){} ; // use initialization list
  private:
     int myX;
};

Example example3(5); // ok
Example example3 = 5; // ok

请注意,我定义的 的构造函数用作默认构造函数。

更具体地说,示例3中的构造函数样式通常是构造函数是显式的情况。

class Example{
  public:
  explicit Example(int x = 0):x(myX){} ; // use initialization list
  private:
     int myX;
};

Example example3(5); // ok
Example example3 = 5; // not allowed

您可能希望阅读此FAQ以获取有关在构造函数中使用初始化列表的更多信息。