AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-23571032

Rabbitx's questions

Martin Hope
Rabbitx
Asked: 2025-04-07 21:58:58 +0800 CST

Como funciona a inicialização de lista entre colchetes "class({args...})"?

  • 6

Tão confuso com a inicialização da lista cpp e a divergência do compilador.

Isso aconteceu enquanto eu estava revisando alguns recursos do cpp.

U ({ arg1, arg2, ... }) (11)

cppreference #copy-list-initialization case 11 diz

expressão de conversão funcional ou outras invocações de construtor, onde uma lista de inicializadores entre chaves é usada no lugar de um argumento do construtor. A inicialização da lista de cópias inicializa o parâmetro do construtor (observe que o tipo U neste exemplo não é o tipo que está sendo inicializado por lista; U's constructor's parameteré)

Então tentei o seguinte código para ver qual construtor o compilador Cpp escolherá:

#include <string>
#include <vector>
#include <map>
#include <tuple>
#include <iostream>
using namespace std;
struct A {
    static int id;
    A(int integer, float sci, string str, vector<int> vnum, pair<int, int> intP, tuple<int, string, float> isfTuple) {
    }
    A(pair<int, float> ifP) { // this also allows {} for default construction
    }
    A(const A &) = delete;
    A(A &&) = delete;
    ~A() {
        cout << "Destructed: " << ++id << endl;
    }
};

int main(){
    A b({1, 1, "str", {1, 2}, {1, 1}, {1, "str", 1}}); // works on MinGW
    // MinGW version: x86_64-14.2.0-release-win32-seh-ucrt-rt_v12-rev2
    // MSVC error: 'A::A(A &&)': attempting to reference a deleted function


    A partial({1, 1.0}); // works both on MinGW and MSVC with ISO C++20 Standard (/std:c++20)
}

No caso em questão A b(...), fiquei confuso sobre o motivo pelo qual o compilador funciona mesmo com o construtor de cópia A(const A &) = delete;e o construtor de movimento A(A&&)excluídos. Então, pesquisei sobre a conversão de construtores , a elisão de cópia e o rascunho de CPP em inicializadores, mas fiquei ainda mais confuso. Tentei compilar com MSVC e obtive o erro:

'A::A(A &&)': tentando referenciar uma função excluída

Então o Compiler Explorer obteve sucesso.

Então, o que está acontecendo? Bug no compilador MinGW ou MSVC? Ou este é um comportamento indefinido (mas o caso 11 parece estar bem definido)? Por que o MinGW e o Compiler Explorer tiveram sucesso?

Meus scripts de construção do GCC (usando vscode tasks.json):

g++ -Wall --std=gnu++20 -g ${file} -o ${fileDirname}\\${fileBasenameNoExtension}

Plataforma: Windows 11, é claro.

Conjunto de ferramentas do Visual Studio:Visual Studio 2022 (v143)

Padrão de linguagem do Visual Studio:ISO C++20 Standard (/std:c++20)

Resultado do Compiler Explorer


Editar:

Meus testes posteriores mostram que tanto o MSVC quanto o MinGW usam os mesmos construtores para cada caso se nenhum construtor for removido -- Result . O resultado do stdio permanece o mesmo. Há apenas uma divergência no comportamento de verificação do compilador (não sei qual é realmente) e o resultado da compilação é o mesmo, novamente, se nenhum construtor for removido. E sob -std=gnu++11, onde a eliminação de cópia não está disponível até o C++17, tanto o MSVC quanto o MinGW mantêm a mesma saída -- nenhum construtor de cópia/movimentação foi usado.

Então A b..., na verdade, o caso de uso 1 é uma sintaxe de inicialização direta, em vez do caso 11, o que faz a sintaxe do caso 1 entrar em conflito com o caso de teste, A b...ou ele está, na verdade, usando outra coisa?


Editar:

Parece que a elisão de cópia sempre acontece desde o C++ 11 durante a inicialização, mas algumas divergências acontecem no processamento de pré-valor na atribuição e na expressão de retorno entre compiladores. Acredito que a melhor prática é evitar aproveitar as vantagens mínimas do efeito colateral dos construtores.


Editar:

Acho que @Jarod42 está certo.

c++
  • 2 respostas
  • 122 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Reformatar números, inserindo separadores em posições fixas

    • 6 respostas
  • Marko Smith

    Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não?

    • 2 respostas
  • Marko Smith

    Problema com extensão desinstalada automaticamente do VScode (tema Material)

    • 2 respostas
  • Marko Smith

    Vue 3: Erro na criação "Identificador esperado, mas encontrado 'import'" [duplicado]

    • 1 respostas
  • Marko Smith

    Qual é o propósito de `enum class` com um tipo subjacente especificado, mas sem enumeradores?

    • 1 respostas
  • Marko Smith

    Como faço para corrigir um erro MODULE_NOT_FOUND para um módulo que não importei manualmente?

    • 6 respostas
  • Marko Smith

    `(expression, lvalue) = rvalue` é uma atribuição válida em C ou C++? Por que alguns compiladores aceitam/rejeitam isso?

    • 3 respostas
  • Marko Smith

    Um programa vazio que não faz nada em C++ precisa de um heap de 204 KB, mas não em C

    • 1 respostas
  • Marko Smith

    PowerBI atualmente quebrado com BigQuery: problema de driver Simba com atualização do Windows

    • 2 respostas
  • Marko Smith

    AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos

    • 1 respostas
  • Martin Hope
    Fantastic Mr Fox Somente o tipo copiável não é aceito na implementação std::vector do MSVC 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant Encontre o próximo dia da semana usando o cronógrafo 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor O inicializador de membro do construtor pode incluir a inicialização de outro membro? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský Por que os conceitos do C++20 causam erros de restrição cíclica, enquanto o SFINAE antigo não? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul O C++20 mudou para permitir a conversão de `type(&)[N]` de matriz de limites conhecidos para `type(&)[]` de matriz de limites desconhecidos? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann Como/por que {2,3,10} e {x,3,10} com x=2 são ordenados de forma diferente? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller O ponto e vírgula agora é opcional em condicionais bash com [[ .. ]] na versão 5.2? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench Por que um traço duplo (--) faz com que esta cláusula MariaDB seja avaliada como verdadeira? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng Por que `dict(id=1, **{'id': 2})` às vezes gera `KeyError: 'id'` em vez de um TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob: MobileAds.initialize() - "java.lang.Integer não pode ser convertido em java.lang.String" para alguns dispositivos 2024-03-20 03:12:31 +0800 CST

Hot tag

python javascript c++ c# java typescript sql reactjs html

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve