0

I am trying to read a file to a vector and I got to this nice post, which contains 2 methods of doing this.(I will ignore non-important lines)

std::ifstream testFile("testfile", std::ios::binary);

std::vector<char> fileContents((std::istreambuf_iterator<char>(testFile)),
                               std::istreambuf_iterator<char>());

std::vector<char> fileContents;
fileContents.assign(std::istreambuf_iterator<char>(testFile),
                    std::istreambuf_iterator<char>());

My code (C++ 11) suits a lot better for the second approach (I need the vector constructed very early), but from CPP documentation it seems that in the first solution, the constructor will add emplace-constructed values, compared to the "assign" method which will create new objects and add them to the vector, thus making copies.

Is there a solution to assign the vector later but without making copies?

Thanks

Community
  • 1
  • 1
Taw
  • 479
  • 3
  • 15
  • You can keep a pointer to `fileContents`. So that you can create the object later. This may defeat the purpose of 'micro-optimisation'. Not the best way, but there I shared it. – Vinayak Garg Apr 12 '17 at 09:11
  • 1
    Since you are talking about chars, it doesn't matter if your move (or emplace) or copy. – OutOfBound Apr 12 '17 at 09:12
  • vectors make copies. If you are really worried about memory, you can make a vector of pointers, which will later point to the strings. – Elan Apr 12 '17 at 09:13
  • Thanks for the answers, yes, a pointer it's a possible solution, at the moment I am using these lines to add to it later, which I really don't like. `for (auto it = (std::istreambuf_iterator(ifs)); it != std::istreambuf_iterator(); it++) { file_contents.emplace_back(*it); }` – Taw Apr 12 '17 at 09:28

2 Answers2

0

Maybe can you swap your vector with a new one:

std::vector<char> fileContents;
std::vector<char> newContents((std::istreambuf_iterator<char>(testFile)),
                               std::istreambuf_iterator<char>());
std::swap(fileContents, newContents);
piwi
  • 5,136
  • 2
  • 24
  • 48
0

According to the standard given a container a<T> for

a.assign(i,j)

to work

Each iterator in the range [i,j) shall be dereferenced exactly once.

and eventually

Replaces elements in 'a' with a copy of [i, j).

So in summary you cannot assign the vector later without making copies.

pcodex
  • 1,812
  • 15
  • 16
  • Yes, I understood that, that's why I searched for another solution.I am not sure if this make duplicates also: `std::move(std::istream_iterator(ifs),std::istream_iterator(), std::back_inserter(file_contents));` – Taw Apr 12 '17 at 11:23
  • Looking at your original query I am not really sure why this is a concern. You aren't really creating duplicates in-memory. The source is on persistent storage while the vector is the only copy in-memory. – pcodex Apr 13 '17 at 14:31
  • I am not sure, but I thought that there are 2 copies (besides the persistent storage): the ifstream and the vector. – Taw Apr 13 '17 at 18:42
  • The stream is transient. You will need to close it once the transfer is done to the vector. – pcodex Apr 13 '17 at 23:44