Qual é a maneira mais barata de inicializar a std::vector
partir de uma matriz no estilo C?
Exemplo: Na classe a seguir, eu tenho um vector
, mas devido a restrições externas, os dados serão passados como uma matriz no estilo C:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
Obviamente, eu posso ligar w_.resize()
e depois fazer um loop sobre os elementos, ou ligar std::copy()
. Existem métodos melhores?
Respostas:
Não esqueça que você pode tratar os ponteiros como iteradores:
fonte
assign
é certamente livre para usá-las para otimizar; pelo menos no VC ++, ele realmente faz exatamente isso.v.end()
um iterador apontando um após o final com vetor em um caso semelhante). Se você receber uma afirmação, algo está errado em outro lugar.Você usa a palavra inicializar, portanto, não está claro se essa é uma atribuição única ou pode ocorrer várias vezes.
Se você precisar apenas de uma inicialização única, poderá colocá-la no construtor e usar o construtor de vetor de dois iteradores:
Caso contrário, use assign como sugerido anteriormente:
fonte
Você pode 'aprender' o tamanho da matriz automaticamente:
Felizmente, você pode alterar a interface para set_data como acima. Ele ainda aceita uma matriz no estilo C como seu primeiro argumento. Acontece apenas por referência.
Como funciona
[Atualização: Veja aqui para uma discussão mais abrangente sobre como aprender o tamanho]
Aqui está uma solução mais geral:
Isso funciona porque a matriz está sendo transmitida como uma referência a uma matriz. No C / C ++, você não pode passar uma matriz como uma função; em vez disso, ela se deteriorará para um ponteiro e você perderá o tamanho. Mas em C ++, você pode passar uma referência para a matriz.
Passar uma matriz por referência requer que os tipos correspondam exatamente. O tamanho de uma matriz faz parte de seu tipo. Isso significa que podemos usar o parâmetro N do modelo para aprender o tamanho para nós.
Pode ser ainda mais simples ter essa função que retorna um vetor. Com as otimizações apropriadas do compilador em vigor, isso deve ser mais rápido do que parece.
fonte
return { begin(source_array), end(source_array) };
também é possível #Bem, Pavel estava perto, mas há ainda uma solução mais simples e elegante para inicializar um contêiner seqüencial a partir de uma matriz de estilo CA.
No seu caso:
fonte
array
matriz real (o que geralmente significa que você está copiando de uma matriz global ou local (declarada na função atual)). No caso do OP, ele está recebendo um ponteiro e um comprimento, e como não está modelado no comprimento, eles não podem mudar para receber um ponteiro para uma matriz de tamanho ou algo assim, portantostd::end
não funcionará.vector
não sobrecarregaoperator()
, portanto, isso não será compilado.std::end
ser chamado em um ponteiro também não serve para nada (a pergunta pede para atribuir um vetor de um ponteiro e uma variável de comprimento separada). Ele iria melhorar a sua resposta para mostrar mais contexto sobre o que você está tentando sugerirA resposta genérica rápida:
ou pergunta específica:
com base no exposto acima : não esqueça que você pode tratar os ponteiros como iteradores
fonte
std::vector<double>::assign
é o caminho a seguir, porque é pouco código . Mas como isso funciona, na verdade? Não redimensiona e copia? Na implementação do STL pela Microsoft, estou usando exatamente o mesmo.Receio que não haja uma maneira mais rápida de implementar (re) inicializar o seu
std::vector
.fonte