Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::copy result different from string constructor

Tags:

c++

I've encountered some strange behaviour when using std::copy. With

std::vector<std::string> chosenIDs{...};
for (const auto& x : chosenIDs) {
  std::string strID("");
  std::copy(std::begin(x), std::find(std::begin(x), std::end(x), '.'), std::begin(strID));
  std::cout << strID << "\n";
}

the strID string contains characters it's not supposed to, however

std::vector<std::string> chosenIDs{...};
for (const auto& x : chosenIDs) {
  std::string strID(std::begin(x), std::find(std::begin(x), std::end(x), '.'));     
  std::cout << strID << "\n";
}

works completely fine. It's clear to me that I should be using the second approach, but it still baffles me as to why the behaviour in the first snippet is different from the second one.

I'm using GCC 5.4.0

like image 306
Jakub Jůza Avatar asked Apr 05 '26 18:04

Jakub Jůza


2 Answers

When using std::copy() it is necessary to make sure that neither range makes out of bounds accesses. The target range starts out empty and there isn't anything done to expand it. Thus, the result is undefined behavior.

The problem can be fixed, e.g., by using a destination iterator growing the target sequence:

std::copy(std::begin(x), std::end(x),
            std::back_inserter(strID));
like image 57
Dietmar Kühl Avatar answered Apr 12 '26 10:04

Dietmar Kühl


As @M.M said: The copy writes out of bounds of strID (copy does not resize the destination). You could use std::back_inserter(strID) as the third argument instead. std::back_inserter

like image 26
Mara Black Avatar answered Apr 12 '26 09:04

Mara Black