Propriedades de um ponteiro para uma matriz de comprimento zero

21

Considerar

int main()
{
    auto a = new int[0];
    delete[] a; // So there's no memory leak
}

Entre a inicialização e a exclusão da cópia, você pode ler o ponteiro em a + 1?

Além disso, o idioma permite que o compilador seja definido acomo nullptr?

Bathsheba
fonte
2
@ Fararor: Você pode ler acom certeza (certamente não pode desreferê-lo).
Bathsheba
8
@RasmiRanjanNayak: Isso é besteira.
Bathsheba
2
@RasmiRanjanNayak Oh meu ... não
Ted Lyngmo
11
@TedLyngmo: Quando digo "leia o ponteiro em a + 1", o código a seguir é um auto b = a + 1;comportamento indefinido? (Eu acho que é).
Bathsheba
2
@ Ayxan Eu acho que no caso em que 0é realmente o resultado de alguma expressão que você não saberá até o tempo de execução. Como new int[0]é seguro, pode poupar a preocupação com alguns casos especiais / ramificações. Imagine se eu fosse inicializar um std::vectorcom std::vector<int> v(0);.
scohe001

Respostas:

3
    auto a = new int[0];

De acordo com [basic.compound.3] , o valor armazenado em adeve ser um dos seguintes:

  1. Um ponteiro para um objeto (do tipo int)
  2. Um ponteiro após o final de um objeto
  3. Nulo
  4. Inválido

Podemos descartar a primeira possibilidade, pois não havia objetos do tipo intconstruídos. A terceira possibilidade é descartada, pois o C ++ exige que um ponteiro não nulo seja retornado (consulte [basic.stc.dynamic.allocation.2] ). Assim, temos duas possibilidades: um ponteiro após o final de um objeto ou um ponteiro inválido.

Eu estaria inclinado a ver acomo um ponteiro do passado, mas não tenho uma referência respeitável para estabelecer isso definitivamente. (Há, no entanto, uma forte implicação disso em [basic.stc] , vendo como você pode usardelete esse ponteiro.) Portanto, vou apresentar as duas possibilidades nesta resposta.

Entre a inicialização e a exclusão da cópia, você pode ler o ponteiro em a + 1?

O comportamento é indefinido, conforme ditado por [expr.add.4] , independentemente de qual possibilidade acima se aplique.

Se afor um ponteiro passado-final, é considerado apontar para o elemento hipotético no índice 0de uma matriz sem elementos. Adicionar o número inteiro ja aé definido apenas quando 0≤0+j≤n, onde né o tamanho da matriz. No nosso caso, né zero, então a soma a+jé definida apenas quando jé 0. Em particular, a adição 1é indefinida.

Se afor inválido, cairemos claramente em "Caso contrário, o comportamento será indefinido". (Não é de surpreender que os casos definidos abranjam apenas valores válidos de ponteiro.)

Além disso, o idioma permite que o compilador seja definido acomo nullptr?

Não. Do [basic.stc.dynamic.allocation.2] mencionado acima : "Se a solicitação for bem-sucedida, o valor retornado por uma função de alocação substituível é um valor de ponteiro não nulo" . Há também uma nota de rodapé destacando que o C ++ (mas não C) requer um ponteiro não nulo em resposta a uma solicitação zero.

JaMiT
fonte
11
Se fosse um valor de ponteiro inválido, você terá sérios problemas com eel.is/c++draft/basic.stc#4
TC
@TC True, isso implica fortemente que não pode ser um valor de ponteiro inválido.
JaMiT 17/03
23

De acordo com a recente discussão do refletor do CWG como resultado da edição editorial 3178 , new int[0]produz o que atualmente é chamado de valor do ponteiro "passado-o-fim" .

Daqui resulta que anão pode ser nulo e a + 1é indefinido por [expr.add] / 4 .

TC
fonte
4
"De acordo com a recente discussão do refletor do CWG como resultado da edição editorial 3178, new int[0]produz o que atualmente é chamado de valor do ponteiro" passado-o-fim "" Isso não é exato. Não houve muita discussão. Uma pessoa sugeriu que o valor deveria ser "ponteiro após o final de um objeto", e essa declaração foi questionada porque, no caso de uma matriz com 0elementos, não há objeto para o qual terminar após o final.
Language Lawyer
@LanguageLawyer parece que não há dúvida de que a + 1é indefinido em qualquer caso, então seu argumento diz respeito apenas à possibilidade de aser nulo?
MM
Não pareceu haver nenhuma discordância sobre a semântica pretendida, nem que o nome atual para esta categoria de valores de ponteiro seja um ajuste inadequado para esse cenário.
TC
@ MM Acho que isso a + 1é indefinido e talvez o valor resultante do ponteiro seja chamado de "ponteiro após o fim". Não estou dizendo que a resposta está errada. É um pouco impreciso, porque poderia ser entendido como uma longa discussão com um consenso que apenas especificando que o resultado é "apontador para o final" é suficiente para resolver o problema. O problema com "ponteiro após o fim" é que ele já passou do final de algum objeto e a subtração 1desse valor de ponteiro fornece um ponteiro para o objeto, o que provavelmente não deve ser o caso de matrizes de 0elementos.
Language Lawyer
2
@Bathsheba Você acha que poderia haver algo mais autoritário sobre as palavras com defeito?
Language Lawyer