【问题标题】:Initialize a dynamic C array within a C++ initializer list在 C++ 初始化程序列表中初始化动态 C 数组
【发布时间】:2023-03-19 15:10:02
【问题描述】:

大多数人可能会建议我使用std::vector 甚至std::array,但是下面的自定义数组类使用C 数组并且它可以工作,我只需要解释一下它为什么工作。

作为参考,这里是初始化动态 C 样式数组的常用方法:

int* elements = new int[size];

现在下面,我们有自己的自定义数组类,它在初始化列表中初始化一个动态 C 样式数组。问题是我不明白 C 数组是如何在 初始化程序列表中初始化的

class myArray 
{
public:

    myArray(int size) : size(size), elements(new int[size])
    {
        std::cout << "Constructed array of size " << size << std::endl;
    }

    ~myArray()
    {
        delete[] elements;
        std::cout << "Deleted elements" << std::endl;
    }

    int getSize() const { return size; }

private:
    int size;
    int* elements;  // our C style array
};

谢谢

更新

我想进一步澄清我的问题。下面是我通常初始化动态 C 数组的老式“赋值”方式:

myArray(int size)
{
    elements = new int[size];
    // elements(new int[size]); // why will line only work in initializer list?
    std::cout << "Constructed array of size " << size << std::endl;
}

但请参阅注释行。为什么这不起作用,但它在初始化列表中起作用?

【问题讨论】:

  • 下面的自定义数组类使用了一个 C 数组并且它可以工作 ...不,它真的不工作。尝试复制myArray 实例。见rule of three
  • @Praetorian,我想让课程尽可能简洁。我对这个例子中的任何其他构造函数都不感兴趣。请参阅更新,我在我的问题中添加了更多信息。查看注释掉的行。我想知道为什么注释行只在初始化列表中起作用。
  • 这就是 C++ 构造函数初始化程序的工作方式。它类似于构造函数的参数。你读过a good C++ book吗?我强烈推荐 C++ 编程语言。这是一项回报丰厚的投资。
  • 注释行无法编译,因为初始化和赋值之间存在差异。 This answer 很好地解释了事情。而且你真的应该从一本书而不是随机代码示例中学习 C++。
  • 这是赋值和构造的区别。您只能使用该函数式语法来分配一个值作为构造的一部分。在初始化列表中,它实际上是在构造 elements 作为构造 myArray 实例的一部分。但是,作为函数体中语句的一部分,编译器将其视为调用函数的尝试。

标签: c++ c++11 initializer-list


【解决方案1】:

我不明白 C 数组是如何在初始化列表中初始化的。

这里:

myArray(int size) : size(size), elements(new int[size])

elements基本上是new int[size]返回的赋值

你可以改写成:

myArray(int size)
{
    this->size = size;
    elements = new int[size];
    std::cout << "Constructed array of size " << size << std::endl;
}

[编辑]

这个:

// elements(new int[size]); // why will line only work in initializer list?

在函数体中不起作用,因为在这个地方编译器认为你要调用一个名为elements的函数,但是没有这个函数。

它在初始化列表中起作用的事实是因为这就是语言语法的制作方式。

【讨论】:

  • 我熟悉初始化数组,就像在您的代码示例中一样。有关我的问题的更多详细信息,请参阅更新帖子。
  • @CarolineBeltran 当编译器在函数体中看到elements(new int[size]); 时,它认为elements 是一个函数。这就是为什么函数体中不允许使用此构造的原因。
  • 顺便说一句。您还可以找到带有大括号初始化的初始化器列表,例如:size{size},与size(size) 的区别在于前者禁止缩小转换。
  • 这就是c++语言的语法,每种语言都有自己的语法,不管是英文还是C++都没有区别,C++可以看这里eel.is/c++draft/gram.special它的mem-initializer-list。 (elements = new int[size]) 无效,因为编译器在 ( 之前需要类成员或基类名称。
  • C++ 语法相当复杂,从这个链接你可能会发现表达式列表允许在初始化列表中使用相当复杂的逻辑,例如myArray(int size) : size(size), elements(this-&gt;elements = new int[size]) - 我不鼓励这样做,因为它没有意义.这会更有意义:myArray(int size) : size(size), elements(size==0?nullptr:new int[size])
【解决方案2】:

有两种初始化方式。第一种方法是普通(文字)类型初始化。第二种方式是非平凡类型 init。

有关这些类型之间的区别,请参阅What is a non-trivial constructor in C++?

您还可以看到,如果您手动调用默认构造函数或可以隐式调用默认构造函数,那么微不足道的行为可能会有所不同。这将确定内存是否在分配时被初始化(zerofill)。

您可以在 Anthony Williams “C++ Concurrency in Action: Practical Multithreading”一书中找到有关隐藏初始化的一些有用信息

【讨论】:

  • 我将阅读您指示我访问的信息,但如果可能,请查看我原始帖子的更新,其中包含我不理解的更多详细信息。
猜你喜欢
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 2021-09-22
  • 1970-01-01
  • 2017-07-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多