Demonstrates possible bug that appears as early as GCC-4.7 up to GCC-5.1 (at least). Affecting C++11, C++14, but not C++98 (assuming 98's inability to elide the copy has the same effect as generate_strings_v2
).
Is this an error or misunderstanding on my part, or a legitimate bug?
Edit: This question asks how the contents of functions that should return identical results are able to impact data sharing in an external assignment. However, as it turns out, implementations of std::string
utilizing copy-on-write are non-compliant for modern C++, making this an non-issue.
// or using deque/list makes no difference.
using stringset = std::vector<std::string>;
// @bug strings do not share data on first reassignment of result.
stringset generate_strings_v1(int count, int length)
{
stringset set(count);
for (auto& x : set) {
x.resize(length);
std::fill(x.begin(), x.end(), 'a');
}
return set;
}
// works as expected.
stringset generate_strings_v2(int count, int length)
{
stringset set(count);
for (auto& x : set) {
x.resize(length);
std::fill(x.begin(), x.end(), 'a');
}
return stringset(set);
}
void test(const char* header, std::function<stringset(int, int)> genstrings,
int count, int length)
{
auto data_ptr_eq = [](const std::string& a, const std::string& b)
{
return a.data() == b.data();
};
stringset a = genstrings(count, length);
stringset b = a;
if (std::equal(a.begin(), a.end(), b.begin(), data_ptr_eq))
std::cout << header << " : data pointer match\n";
else {
std::cout << header << " : data pointer mismatch\n";
assert(a == b); // not expected; just in case.
}
}
int main(int argc, char* argv[])
{
int count = 1, length = 1;
assert(length > 0 && count > 0);
test("v1", generate_strings_v1, count, length);
test("v2", generate_strings_v2, count, length);
return 0;
}
Extended code and output may be viewed here.