unique_ptr <0 OU o que faz menos que o operador?


9

Estou lidando com código que não foi escrito por mim. Eu tenho esta afirmação:

// p is type of std::unique_ptr<uint8_t[]>
if (p < 0) { /* throw an exception */ }

Então, o que p < 0significa nesse contexto?
Na página de documentação , acredito que meu caso é 16) y < nullptr, onde 0está nullptr.

mas o que isso faz?


11
Com base no fato de que, em x64, os ponteiros canônicos no intervalo do kernel têm o bit superior definido, pode ser uma maneira (estúpida) de verificar se um ponteiro pertence ao espaço do kernel - se a resposta abaixo estiver correta, então não .
Michael Chourdakis 15/01

11
No WINAPI p==-1é um identificador inválido. Como 2^64é um número ridiculamente grande, qualquer sensível pé sempre positivo. Portanto, p<0verifica se há identificador inválido do WINAPI. Este não é um bom código.
ALX23z 15/01

@OP: Você poderia esclarecer um pouco em que contexto esse código é usado? É usado no Linux ou Windows? O valor do ponteiro está relacionado a algum código WINAPI? Acho que se você esclareceu isso, os comentários acima podem ser boas respostas.
noz

@ ALX23z Mas um manipulador WINAPI deve ser do tipo uint8_t*(ou mesmo matriz de uint8_t)? Eu acho que eles são void*, não são?
noz

@ Walnut eles não são void*eles têm macro HANDLE_PTR ou algo que é basicamente long*IIRC.
ALX23z 16/01

Respostas:


2

unique_ptr <0 OU o que faz menos que o operador?

Corresponde à sobrecarga (11) na preferência operator<(const unique_ptr&, nullptr_t);. 0 converte implicitamente em std::nullptr_t. Conforme a documentação, o resultado é std::less<unique_ptr<T,D>::pointer>()(x.get(), nullptr).

O resultado é uma implementação definida, mas incondicionalmente falsa provavelmente na maioria dos sistemas. Presumivelmente, em um sistema exótico em que null não tem a representação binária de 0, o resultado pode ser verdadeiro.

Eu acredito que meu caso é 16)

(16) é o mesmo em torno de outra maneira: 0 > unique_ptr. O resultado é o mesmo.


Mas é 0considerado nullptrpelo compilador? Eu acho que é isso que ele está se perguntando. Também não faz sentido para mim.
alteredinstance 15/01

@alteredinstance 0 não é "considerado" nullptr(ou depende do que você entende por consideração). 0 converte implicitamente em std::nullptr_t.
eerorika 15/01

Foi o que eu assumi. Gostaria de saber se existe alguma documentação sobre a conversão implícita de 0para nullptr, já que eu só vi as duas compatíveis com comparações booleanas. São comparáveis, mas fiquei com a impressão de que não são conversíveis.
alteredinstance 15/01

@alteredinstance A conversão não acontece ao contrário. int x = nullptrestá mal formado.
eerorika 15/01

2
O @alteredinstance std::nullptr_tfoi projetado para ser utilizável com qualquer constante de ponteiro nulo; não apenas nullptr. 0 (assim como 0L, por exemplo) são constantes de ponteiro nulo; portanto, é intenção que elas possam ser usadas para criar a std::nullptr_t.
eerorika 15/01

2

Verifique operator <se não está sobrecarregado em algum lugar da sua base de código. Essa parece ser a única maneira de como (p < 0)poderia ser true.

Exemplo:

bool operator< (const std::unique_ptr<uint8_t[]>&, int) { return true; }

int main() {
    std::unique_ptr<uint8_t[]> p;
    std::cout << (p < 0) << std::endl;
}

Impressões:

1

demonstração ao vivo

Caso contrário, como outros já disseram, 0converte implicitamente em std::nullptr_t, o que selecionaria a bool operator<(const unique_ptr<T, D>& x, nullptr_t)sobrecarga que chamaria std::less(p, 0)que retornaria false(mesmo no Windows com um -1valor de ponteiro).


Não necessariamente retorna false. É definido pela implementação ou não especificado (não tenho certeza.) Mas concordo que provavelmente retornará falsena maioria das implementações (todas?). Veja também a resposta de @eerorika
walnut

0

Essa expressão corresponde ao operador do modelo (0 sendo convertido em nullptr):

template <class T, class D>
bool operator<(const unique_ptr<T, D>& x, nullptr_t);

Retorna o std::less<unique_ptr<T,D>::pointer>()(p.get(), nullptr)que é sempre falso (como std::lessé um functor de ordem estrita) ( demo ).


Nem sempre retorna false. Se isso ocorre, é definido ou não da implementação. Ele provavelmente sempre retorna falsena maioria das implementações atuais (todas?).
noz

@walnut A menos que uma pergunta explique explicitamente sobre o que o Padrão diz (por meio da etiqueta de advogado de linguagem, por exemplo), tento responder de um ponto de vista prático. Toda implementação prática de std::lessretorno false.
YSC 16/01

Tudo bem, eu simplesmente não achei o seu raciocínio (" como std :: less é um functor estrito de ordem ") convincente. Pode ser uma ordem estrita sem retornar false. A razão prática seria que o valor do ponteiro zero é representado pelo endereço mais baixo possível ou algo nesse sentido.
walnut
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.