使用 class 构造函数初始化指向 class 对象的指针?

pointer to class objects initialization with class constructor?

// pointer to classes example
// runs with no problem
#include <iostream>
using namespace std;

class Rectangle {
  int width, height;
public:
  Rectangle(int x, int y) : width(x), height(y) {}
  int area(void) { return width * height; }
};


int main() {
  Rectangle obj (3, 4);
  Rectangle * foo, * bar, * baz;
  foo = &obj;
  bar = new Rectangle (5, 6);
  baz = new Rectangle[2] { {2,5}, {3,6} };
  cout << "obj's area: " << obj.area() << '\n';
  cout << "*foo's area: " << foo->area() << '\n';
  cout << "*bar's area: " << bar->area() << '\n';
  cout << "baz[0]'s area:" << baz[0].area() << '\n';
  cout << "baz[1]'s area:" << baz[1].area() << '\n';       
  delete bar;
  delete[] baz;
  return 0;
}   

我对这里的这行代码有点(没有双关语意)困惑:

baz = new Rectangle[2] {{2,5}, {3,6}};

我见过这样的代码:

int *foo = new int[3] {1,2,3};

我完全理解。但是这里 {{2,5}, {3,6}} 的语法是什么? class 对象数组如何像这样初始化?我搜索了很多在线 c++ 参考资料,但没有任何线索。

只需使用初始化列表来填充数组中的两个矩形。

想到:

{2,5}, {3,6}

就像调用 Rectangle{2,5}、Rectangle{3,6} 一样。

Rectangle 构造函数需要两个 int。 如果你看行 Rectangle obj (3, 4); 这也可以是 Rectangle obj {3, 4};

baz = 新矩形[2] { {2,5}, {3,6} };

不可编译。

甚至,

int * abc = new int[3] {1,2,3} ;

不可编译。

如果您想使用非默认构造函数创建一个矩形 class 数组,请执行以下操作:

  Rectangle baz[] = { Rectangle(2,5) ,  Rectangle(3,6) };

如有不明之处请告知

(注意这只适用于C++11及以后的版本)

baz = new Rectangle[2] { {2,5}, {3,6} };

此语法称为 list-initialization

列表初始化一个集合,例如数组结果(不出所料)在每个元素上 aggregate initialization, which will perform copy-initialization;由于此处的初始化程序本身是列表,因此导致 copy-list-initialization.

当您列表初始化一个(非聚合)class 时,编译器会查找构造函数并选择最佳匹配。如果所选构造函数需要对任何参数进行缩小转换(例如 double -> int),或者如果它是 explicit 构造函数,此时您将收到错误消息因为 copy-list-initializationcopy-initialization 的一种形式;只有 direct-initialization 例如 Rectangle r{2, 5}; 可以使用 explicit 构造函数(尽管缩小转换仍然是一个错误)。

使用 C++11 可以使用 {x, y, z} 初始化对象实例。例如:

struct P2d {
    double x, y;
};

void foo(P2d p);

void bar() {
    foo({10, 20}); // Compiles fine
}

用在数组上可以,简单的情况下也可以。在更复杂的情况下,它只会增加混乱,因为您只能看到这些值,但您不知道这些值的用途。

这就像 API 像

一样使用
 createWindow(0, 0, true, NULL, NULL, 1, NULL, false);

这些值有什么用?

只是不要过度使用新的大括号初始化...有些情况下它很棒:

// C++03
std::vector<int> list_of_values() {
    std::vector<int> result;
    result.push_back(1);
    result.push_back(2);
    result.push_back(3);
    return result;
}

// C++11
std::vector<int> list_of_values() {
    return {1, 2, 3};
}

但有些情况只会让事情变得更糟:

{Rect(2, 3), Rect(4, 5)}

实际上比

更具可读性
{{2, 3}, {4, 5}}

(请记住,阅读代码时的易用性比编写代码时的易用性重要得多...大多数代码行都已编写一次阅读多次)