【问题标题】:pointer to class objects initialization with class constructor?使用类构造函数初始化类对象的指针?
【发布时间】:2015-11-05 20:39:27
【问题描述】:
// 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}} 的语法是什么?如何像这样初始化类对象数组?我搜索了许多在线 c++ 参考资料,但没有任何线索。

【问题讨论】:

  • {2,5} 初始化第一个数组成员,{3,6} 初始化第二个数组成员。它与int[3] 的情况没有什么不同,只是每个初始化器都是另一个用大括号括起来的列表。

标签: c++ arrays class c++11 initialization


【解决方案1】:

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

想一想:

{2,5}, {3,6}

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

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

【讨论】:

    【解决方案2】:

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

    不可编译。

    偶数,

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

    不可编译。

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

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

    如果不清楚请告诉我。

    【讨论】:

    • 废话,从 C++11 开始,它是完全有效的语法。
    • 用户没有从 C++11 指定问题。
    • 很明显他是,他只是忘了标记它,事实上我现在会修复它。
    • 不是那么清楚,伙计!如果一个人不知道 C++11 的新语法,那对他来说可能不是一个明显的想法。
    【解决方案3】:

    (请注意,这只适用于 C++11 及更高版本)

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

    此语法称为list-initialization

    aggregate initialization 中对诸如数组之类的聚合进行列表初始化(不出所料),这将对每个元素执行copy-initialization;因为这里的初始化器本身就是列表,这会导致 copy-list-initialization

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

    【讨论】:

      【解决方案4】:

      使用 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}}
      

      (请记住,阅读代码时的轻松度比编写代码时的轻松度要重要得多......大多数代码行都是一次编写并多次阅读)

      【讨论】:

        猜你喜欢
        • 2023-03-12
        • 1970-01-01
        • 2021-11-06
        • 2023-03-14
        • 1970-01-01
        • 2013-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多