If one copies one std::vector into another, or copies elements of a std::vector in a larger (reserve) or smaller (shrink_to_fit) block of heap memory, what constructor of the element's type is called?
In the example program:
#include <vector>
#include <iostream>
struct A {
A() {}
A(A&) { std::cout << "A(A&) "; }
A(const A&) { std::cout << "A(const A&) "; }
};
int main() {
std::vector<A> v(1);
v.reserve(10);
auto w = v;
v.shrink_to_fit();
}
I would expect to see A(const A&) A(const A&) A(const A&) output. But in reality the standard library implementations diverge:
libc++ prints A(const A&) A(A&) A(const A&),libstdc++ prints A(const A&) A(const A&) A(A&),A(A&) A(A&) A(A&).Online demo: https://gcc.godbolt.org/z/TTqxv9sd3
Is it right to assume that if the constructor from not-const lvalue is called, then the user code is allowed modifying its argument (at least temporarily)?
I do not see any reason that the library would be required to ensure that the const overload is used.
The container copy constructor requires per [container.reqmts]/12 that the element type is CopyInsertable from a lvalue v of its type into the container regardless of the const-qualification of v. It also requires the postcondition ([container.alloc.reqmts]/2.4):
The value of v is unchanged and is equivalent to *p.
implying that if the non-const copy constructor is used, then it must not result in the value of the original object being different after the call, at least.
It is a bit less clear to me whether modification of the argument is completely forbidden, because this is stated as postscondition only. I suspect that this is the intent though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With