C ++ 11 удаленные / дефолтные конструкторы - PullRequest
0 голосов
/ 05 декабря 2018

Я немного озадачен тем, как / почему конструкторы вызываются в C ++ 11 и C ++ 17.

#include <iostream>
using namespace std;

//---

template<typename T>
struct StructTest
{
public:
  const T Var = -1;

  //---

  // constexpr StructTest() = delete;  // 1
  // constexpr StructTest() = default; // 2

  // constexpr StructTest(const StructTest &Source) = delete;                  // 3
  // constexpr StructTest(const StructTest &Source) = default;                 // 4
  // constexpr StructTest(const StructTest &Source) {cout << "Copy" << endl;}; // 5
};

//---

StructTest<int> A{};
StructTest<int> A1{1};
StructTest<int> A2(A);

//---

int main(void)
{
  return(0);
};

Поэтому меня смущает то, что происходит, когда я раскомментирую некоторую комбинациюстрок (и компиляция со стандартным флагом c ++ 17 с помощью clang):

  • 1, Компилируется.Перечислите инициалы для A и A1 и конструктор копирования по умолчанию для A2
  • 2, Компилируется.Конструктор по умолчанию для A и список инициализации A1 (?), А также конструктор копирования по умолчанию для A2
  • 1 + 3 или 2 + 3, не компилируется из-за удаленного конструктора копирования для A2
  • 1 + 4, Компиляция.Конструктор по умолчанию для A и списка init A1 (?), И конструктор копирования по умолчанию для A2
  • 2 + 4, Компилируется.Конструктор по умолчанию для A и список инициализации A1 (?), И конструктор копирования по умолчанию для A2
  • 1 + 5, не компилируется.Говорит, A отсутствует (удален) конструктор по умолчанию, и нет соответствующего конструктора для A1?
  • 2 + 5, не компилируется.Нет подходящего конструктора для A1?

Я думаю, я понимаю большинство из этого, но я запутался, почему компиляция 1 + 5 и 2 + 5 не удалась.Может ли кто-нибудь объяснить логику, которую использует компилятор для выбора конструкторов, которые он собирается использовать, и почему он не может скомпилироваться?

Если конструкторы, которые, как мне кажется, вызываются в других случаях, неверны, не могли бы вытакже укажите, что называется и почему?

Ответы [ 3 ]

0 голосов
/ 06 декабря 2018

То, что вы называете list init, на самом деле называется агрегатной инициализацией.Ваш класс является агрегатом во всех случаях, но когда вы раскомментируете строку 5 - в этот момент он перестает быть агрегатом.Агрегатный класс - это класс, в котором все конструкторы имеют значения по умолчанию (явно или неявно) или удалены.У вас есть только один не дефолтный, не удаленный конструктор, поэтому, если вы не раскомментируете это, ваш класс останется агрегатом.

Учитывая это, большая часть вашего примера вращается вокруг инициализации агрегата, за исключением случая, когда выявным образом запретите копирование, удалив конструктор копирования или добавив конструктор копирования без дефолта, и сделайте класс неагрегированным.

Дополнительная информация об инициализации агрегата и агрегата: https://en.cppreference.com/w/cpp/language/aggregate_initialization

0 голосов
/ 06 декабря 2018

(Это дополнительная информация к другим ответам)

Поведение этого кода отличается для C ++ 11, C ++ 14/17 и C ++ 20!Из-за изменяющегося определения агрегат .

В C ++ 11 класс не был агрегатом, потому что он имеет инициализатор скобок или равно (= -1), поэтому случай 1 не будет компилироваться.

В C ++ 14 и 17 класс является агрегатом, другие ответы охватывают этот случай.

В C ++ 20класс не будет снова агрегатом, потому что есть новое правило, согласно которому любой объявленный пользователем конструктор лишает класс возможности быть агрегатом;поэтому случай 1 перестанет компилироваться снова, а в случае 2 StructTest<int> A1{1}; не будет компилироваться из-за слишком большого количества аргументов конструктора и т. д.

0 голосов
/ 06 декабря 2018

1, Компилирует.Перечислите инициалы для A и A1 и конструктор копирования по умолчанию для A2

То, что вы называете Список init , в этом случае на самом деле агрегатная инициализация , потому что StructTest это совокупность.Это разрешено, поскольку наличие явно дефолтного или удаленного конструктора все еще делает класс агрегатным.

2, Компилируется.Конструктор по умолчанию для A и списка init A1? И конструктор копирования по умолчанию для A2

A1 инициализируется агрегатом, как это было в 1. Остальное верно

1 + 3 или 2 + 3, не компилируется из-за удаленного конструктора копирования для A2

Это ожидаемое поведение, поскольку конструктор копирования помечен как удаленный.

1 + 4, Компилирует.Конструктор по умолчанию для A и списка init A1? И конструктор копирования по умолчанию для A2

Опять же, агрегатная инициализация для A и A1

2 + 4Компилирует.Конструктор по умолчанию для A и списка init A1? И конструктор копирования по умолчанию для A2

A и A1 будут инициализированы агрегированно, но при этом он будет использовать инициализатор элемента по умолчанию Var, когдаинициализация A per [dcl.init.aggr] /5.1

1 + 5, не компилируется.Говорит, что в A отсутствует (удален) конструктор по умолчанию, и нет соответствующего конструктора для A1?

5 - это предоставленный пользователем конструктор по умолчанию или удаленный.Это означает, что StructTest больше не является агрегатом, и вы не можете больше его инициализировать.

2 + 5, не компилируется.Нет подходящего конструктора для A1?

По той же причине, что и 1 + 5

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...