В инициализации класса и прямой инициализации в C++ 11/17. Каковы различия?

Когда я вижу этот вебинар CPP Con 2017, Федор Пикус говорит: «Это должна быть прямая инициализация».

enter image description here Это связь на вебинар.

В чем разница между этими методами инициализации? (и, следовательно, почему это должна быть «прямая» инициализация? почему «косвенная» инициализация «НЕ»?)

// C++17 Compiler

#include <atomic>

class Example
{
    std::atomic<bool> m_b1 = false; // 1-h
    std::atomic<bool> m_b2{ false }; // 2-h

    static void example2()
    {
        std::atomic<bool> b1 = false; // 1-f
        std::atomic<bool> b3{ false }; // 2-f
        std::atomic<bool> b2(false); // 3-f

        // Do something
    }
};

@HolyBlackCat, в вебинаре есть ссылка на конкретную временную метку. Это простой пример: thread-1 Read; thread-2 Напишите сценарий, в котором atomic<bool> приходит на помощь вместо простого bool,

Amit 10.04.2022 16:46

@ user17732522 Я исправлен.

HolyBlackCat 10.04.2022 16:51
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
2
2
48
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

std::atomic нельзя копировать или перемещать.

До C++17 инициализация копированием std::atomic<int> x = 0; сначала конструировала временный std::atomic<int> из 0, а затем напрямую инициализировала x из этого временного объекта. Без конструктора перемещения или копирования это потерпит неудачу, и поэтому строка не скомпилируется.

std::atomic<int> x(0);, однако, является прямой инициализацией и просто создаст x с аргументом 0 конструктору.

Так как в C++17 нет временного объекта, и x будет напрямую инициализирован вызовом конструктора с 0 в качестве аргумента в любом случае, поэтому нет проблем с тем, что std::atomic является неподвижным. В этом смысле слайд устарел.

Несмотря на то, что в этом случае поведение для инициализации копированием и прямой инициализации одинаково, в целом между ними все еще есть различия. В частности, прямая инициализация выбирает конструктор для прямой инициализации переменной путем разрешения перегрузки, в то время как инициализация копированием пытается найти неявную последовательность преобразования (возможно, с помощью конструктора преобразования или функции преобразования с другими правилами разрешения перегрузки). Кроме того, инициализация копированием, в отличие от прямой инициализации, не учитывает конструкторы, помеченные explicit.

Что касается фрагмента кода в вопросе. 1-h и 1-f — это инициализация копирования, как указано выше. 3-f — это прямая инициализация, как указано выше. 2-h и 2-f — это прямая инициализация списка, которая в некоторых случаях ведет себя иначе, чем обе другие, но здесь она имеет тот же эффект, что и прямая инициализация со скобками.

Объяснение всех различий между формами инициализации в целом заняло бы некоторое время. Это одна из самых сложных частей C++.

Я всегда думал, что выражение T x = 0; всегда будет пытаться вызвать конструктор T(int) независимо от класса

MatG 10.04.2022 16:53

Итак, начиная с С++ 17, все методы «Прямые» и одинаковые?

Amit 10.04.2022 16:53

@Amit Нет, первый метод по-прежнему является инициализацией копирования, а второй - прямой инициализацией. Просто изменился смысл того, что делает копия-инициализация. Эти два метода по-прежнему различаются по нескольким причинам.

user17732522 10.04.2022 16:55

@MatG См. тимсонг-cpp.github.io/cppwp/n3337/dcl.init#16.6.2, но временное можно опустить. Он вообще не рассматривает конструкторы, вместо этого он пробует определяемые пользователем последовательности преобразования.

user17732522 10.04.2022 16:56

@Amit: Его ответ делает объясняет разницу. В версиях до C++17 создавался временный файл, из которого можно было копировать/перемещать. В пост-С++ 17 этого больше не происходит. Изменилось поведение выражения, а не то, является ли это выражение прямой или копирующей инициализацией. То есть вещь под названием "инициализация копирования" больше не требует "копии" при определенных условиях.

Nicol Bolas 10.04.2022 17:00

@Amit Я думаю, что упомянул различия, которые здесь имеют значение. Перечисление всех различий между двумя формами инициализации, вероятно, займет некоторое время. Я думаю, наиболее важным из них является то, что инициализация копирования не учитывает конструкторы, отмеченные explicit.

user17732522 10.04.2022 17:02

@Amit Возможно, у stackoverflow.com/questions/1051379/… есть дополнительная информация об общем случае.

user17732522 10.04.2022 17:05

Другие вопросы по теме