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 / coding / Perguntas / 79343589
Accepted
Konvt
Konvt
Asked: 2025-01-10 01:54:33 +0800 CST2025-01-10 01:54:33 +0800 CST 2025-01-10 01:54:33 +0800 CST

Uma função pode ser marcada como noexcept se ela assumir um tipo de valor que pode gerar uma exceção?

  • 772

Em C++, eu marco uma função como noexceptnos seguintes casos:

A função em si não gera exceções, mas seus parâmetros de tipo de valor podem gerar exceções durante a construção.

O código a seguir demonstra essa situação:

struct A {
    A(bool will_throw) {
        std::cerr << "Ctor of A\n";
        if (will_throw) throw std::runtime_error("An exception from A");
    }
    A(A&& lhs) noexcept {
        std::cerr << "Move ctor of A\n";
    }
    ~A() noexcept = default;
};

struct B {
    A mem_;

    // Exceptions are thrown during parameter passing, not inside the function
    // Thus it isn't an UB I think.
    B(A value = A(true)) noexcept : mem_{std::move(value)} {/* do nothing */}
    ~B() noexcept = default;
};

Neste código, o construtor de Bé marcado como noexcept, e o A(true)construtor padrão pode lançar uma exceção, mas acredito que isso não leva a um comportamento indefinido, pois a exceção ocorre durante a passagem de parâmetros e não dentro do corpo da função.

O programa de teste está aqui .

Minha pergunta é:

Em casos semelhantes, é seguro marcar o construtor e outras funções com noexcept? Essa prática pode ser aplicada amplamente, especialmente em casos em que a função em si não lança nenhuma exceção?

c++
  • 2 2 respostas
  • 94 Views

2 respostas

  • Voted
  1. Best Answer
    Brian Bi
    2025-01-10T08:21:13+08:002025-01-10T08:21:13+08:00

    Tentar propagar uma exceção de uma noexceptfunção não causa UB. Ele causa std::terminateser chamado.

    Se você não quiser std::terminateser chamado, então ainda é seguro para uma noexceptfunção aceitar um tipo de parâmetro cuja inicialização pode gerar. Veja [expr.call]/6

    [...] A inicialização e destruição de cada parâmetro ocorre dentro do contexto da expressão completa ([intro.execution]) onde a chamada de função aparece.
    [ Exemplo 2 : O acesso ([class.access.general]) do construtor, funções de conversão ou destrutor é verificado no ponto de chamada. Se um construtor ou destrutor para um parâmetro de função lançar uma exceção, qualquer bloco de tentativa de função ([except.pre]) da função chamada com um manipulador que pode manipular a exceção não é considerado. — fim do exemplo ]

    • 4
  2. Yachen
    2025-01-10T10:00:52+08:002025-01-10T10:00:52+08:00

    Em C++, a palavra-chave noexcept é usada para declarar que uma função tem garantia de não lançar exceções. Essa garantia permite que o compilador otimize o código de forma mais eficaz e fornece expectativas mais claras sobre o comportamento de uma função, especialmente em contextos como operações de movimentação dentro de contêineres de biblioteca padrão.

    Ao aplicar noexcept, é importante diferenciar entre exceções que ocorrem dentro do corpo da função e aquelas que acontecem durante a passagem de parâmetros. A especificação noexcept se aplica somente às operações internas da função. Por exemplo, no código fornecido, o construtor de B é marcado como noexcept, o que é seguro porque quaisquer exceções potenciais da construção do parâmetro padrão A(true) ocorrem antes que o corpo do construtor seja executado e não violam a garantia noexcept do próprio construtor de B.

    As melhores práticas para usar noexcept incluem garantir que todas as operações dentro de uma função sejam livres de exceções antes de marcá-la como noexcept. Isso é particularmente recomendado para construtores de movimentação e operadores de atribuição de movimentação para melhorar o desempenho de contêineres de biblioteca padrão como std::vector . Além disso, usar noexcept condicional em modelos pode fornecer flexibilidade ao permitir que garantias de exceção dependam de parâmetros de modelo. No entanto, marcar incorretamente uma função que pode lançar exceções como noexcept pode levar ao encerramento inesperado do programa por meio de std::terminate , portanto, consideração cuidadosa e testes completos são essenciais.

    • 0

relate perguntas

  • Por que os compiladores perdem a vetorização aqui?

  • Erro de compilação usando CMake com biblioteca [fechada]

  • Erro lançado toda vez que tento executar o premake

  • Como criar um tipo de octeto semelhante a std::byte em C++?

  • Somente operações bit a bit para std::byte em C++ 17?

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