O seguinte programa curto
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
tem um problema de referência pendente, que nenhum compilador parece avisar. A questão é que os temporários podem ser vinculados a const-refs, que você pode manter por aí. A questão então é; Existe um método para evitar entrar nesse problema? De preferência um que não envolva o sacrifício da correção constante, ou sempre fazer cópias de objetos grandes.
std::unique_ptr
para propriedade exclusivastd::shared_ptr
ou propriedade compartilhada oustd::weak_ptr
para, pelo menos, reconhecer dados perdidos).-fsanitize=address
. Não acho que exista nenhuma prática recomendada para evitá-lo sem sacrificar o desempenho.Respostas:
Na situação em que algum método mantém uma referência após o retorno, é uma boa idéia utilizar em
std::reference_wrapper
vez da referência normal:Woop (std::vector<int> const &&) = delete;
para o seu método:fonte
Uma maneira de tornar sua classe menos vulnerável pode ser adicionar um construtor excluído que aceite a referência correta. Isso impediria que sua instância de classe fizesse ligações com temporários.
Esse construtor excluído realmente tornaria o código O / P não compilado, qual pode ser o comportamento que você está procurando?
fonte
Eu concordo com as outras respostas e comentários que você deve pensar cuidadosamente se realmente precisar armazenar uma referência dentro da classe. E se você fizer isso, provavelmente desejará um ponteiro não-const para um vetor const (ie
std::vector<int> const * numbers_
).No entanto, se for esse o caso, acho que as outras respostas atualmente postadas estão fora de questão. Eles estão todos mostrando como fazer
Woop
esses valores.Se você puder garantir que o vetor que você transmite sobreviverá à sua
Woop
instância, poderá desabilitar explicitamente a construção de aWoop
partir de um rvalor. Isso é possível usando esta sintaxe do C ++ 11:Agora seu código de exemplo não será mais compilado. O compilador com um erro semelhante a:
PS: Você provavelmente deseja um construtor explícito, consulte Por exemplo, o que a palavra-chave explícita significa? .
fonte
Para evitar esse caso em particular, você pode optar por usar um ponteiro (uma vez que
Weep(&std::vector<int>{1,2,3})
não é permitido) ou por uma referência não-const, que também causará um erro temporário.Isso ainda não garante que o valor permaneça válido, mas interrompe pelo menos o erro mais fácil, não cria uma cópia e não precisa
nums
ser criado de uma maneira especial (por exemplo, comostd::shared_ptr
oustd::weak_ptr
faz).std::scoped_lock
tomar uma referência ao mutex seria um exemplo, e aquele em que o ptr exclusivo / compartilhado / fraco não é realmente desejado. Muitas vezes, ostd::mutex
será apenas um membro básico ou variável local. Você ainda precisa ter muito cuidado, mas nesses casos geralmente é fácil determinar o tempo de vida.std::weak_ptr
é outra opção para quem não possui, mas força o chamador a usarshared_ptr
(e, portanto, também aloca a pilha), e às vezes isso não é desejado.Se uma cópia estiver correta, isso evita o problema.
Se
Woop
deve assumir a propriedade, passe como um valor r e mova (e evite problemas de ponteiro / referência inteiramente) ou useunique_ptr
se você não puder mover o valor em si ou desejar que o ponteiro permaneça válido.Ou, se a propriedade for compartilhada, você poderá usar
shared_ptr
para tudo, e ela será excluída juntamente com a referência final, mas isso pode fazer com que o controle dos ciclos de vida do objeto fique muito confuso se for usado em excesso.fonte
Você pode usar
template programming
earrays
se quiser ter um objeto que contenha umconst
contêiner. Devido aoconstexpr
construtor econstexpr arrays
você consegueconst correctness
ecompile time execution
.Aqui está um post que pode ser interessante: std :: move a const vector
código de execução
Resultado:
fonte
std::array
este, é garantido que você copiará, mesmo que uma movimentação esteja disponível. Em cima dissowooping1
ewooping2
não são do mesmo tipo, que é menos do que o ideal.