gpt4 book ai didi

c++ - 初始化没有复制构造函数的成员聚合类型

转载 作者:行者123 更新时间:2023-12-02 10:35:16 27 4
gpt4 key购买 nike

我需要使用非默认构造函数而不使用复制构造函数来初始化类的成员数组。

我有以下两个类(class):

class MemberClass
{
public:
MemberClass(int id) { /* Do stuff */ }; // Define non-default ctor
MemberClass(const MemberClass& other) = delete; // Delete copy ctor
~MemberClass() { /* Do stuff */ }; // Overide default dtor
};

class ContainerClass
{
private:
MemberClass mem[2];

public:
ContainerClass(int id)
: mem { {id} , {id} }
{}
};

编译时出现以下错误:
error: use of deleted function ‘MemberClass::MemberClass(const MemberClass&)’
: mem { {id} , {id} }

但我无法找到初始化 mem 的方法没有定义复制构造函数的数组。我从 here 找到了答案和 here解释正在发生复制省略,并且需要一个复制ctor来编译,但应该由编译器删除。 MemberClass永远不应该被复制,所以仅仅为这个初始化定义一个 copy-ctor 似乎很尴尬,并且在其他地方容易调试更困难。

如果 MemberClass只有一个默认构造函数,那么编译器没有给出任何问题。如果 mem 也不存在任何问题不是一个数组,只是一个 MemberClass目的。我唯一的问题是使用非默认 ctor 初始化这个数组,而不使用 copy-ctor。

奇怪的是,如果我不定义析构函数,我不会得到任何编译错误,这似乎是一个线索。

是否有一种“正确”的方式来进行这种初始化?

最佳答案

我认为这是 gcc 中的一个错误。

如 C++17 [dcl.init.aggr]/3 所指定(此文本在 C++14 中基本相同):

When an aggregate is initialized by an initializer list as specified in 11.6.4, the elements of the initializer list are taken as initializers for the elements of the aggregate, in order. Each element is copy-initialized from the corresponding initializer-clause. [...] If an initializer-clause is itself an initializer list, the member is list-initialized,



我将在这里分析三种不同的情况:
  • 案例一:mem { id, id }
  • 案例二:mem { MemberClass{id}, MemberClass{id} }
  • 案例3:mem { {id}, {id} }

  • 在案例 1 中, mem[0]由表达式 id 复制初始化.这与 MemberClass x = id; 的初始化类型相同。 .它被 dcl.init/17.6.2 覆盖(从不同类型的表达式复制初始化)。

    行为是初始化器被转换为纯右值(即 MemberClass{id} ),然后直接初始化目标。在 C++14 中这是不正确的:虽然它是一个复制省略上下文,但仍然必须存在一个有效的复制构造函数。在 C++17 中,它是格式良好的:从相同类型的纯右值初始化对象与使用纯右值指定的构造函数初始化对象相同(所谓的“保证复制省略”)。

    案例 2 类似于案例 1:它使用 17.6.1(从相同类型的表达式初始化)并且适用于案例 1 的相同分析。

    但是,案例 3 不同。根据 dcl.init.aggr/3 的最后一个粗体引用, mem[0]{id} 初始化列表,即代码的行为应与 MemberClass z {id}; 相同.即使在 C++14 中也没有临时或复制操作。

    所以正确的行为是:
  • C++14 - 案例 3 是正确的,案例 1 和 2 格式错误。
  • C++17 - 所有情况都正确。

  • gcc 发出的错误消息表明它在 C++14 模式下正在处理案例 3,即您的代码,与其他两种情况相同。在 C++17 模式下,它从来没有得到关于保证复制省略的备忘录。

    关于c++ - 初始化没有复制构造函数的成员聚合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60606947/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com