问题
I was reading Why would a copy constructor have more than one parameter?.
The accepted answer says that:
The old std::basic_string
does have one too:
basic_string(const basic_string& s,
size_type pos = 0, size_type n = npos)
But http://www.cplusplus.com/reference/string/basic_string/basic_string/ says that:
basic_string (const basic_string& str, size_type pos, size_type len = npos,
const allocator_type& alloc = allocator_type());
The above isn't a copy constructor but substring constructor that copies the portion of str
that begins at the character position pos
and spans len
characters.
C++ standard section says that:
A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments
So, Is the accepted answer from that link is incorrect? Is this really basic_string class constructor for sub-string? I've checked prototype for this in C++98, C++11 & C++14 specification on the link & all shows the same.
回答1:
The specification of the basic_string
class template in the (former) C++11 International Standard [basic.string]p5 contains the following two constructors (among others):
basic_string(const basic_string& str); // ... basic_string(const basic_string& str, size_type pos, size_type n = npos, const Allocator& a = Allocator());
The first one clearly is a copy constructor, the second one is no copy constructor. Note that there is no constructor in the spec where pos
has a default argument.
The situation is essentially the same in C++03, C++14 and C++1z. In C++98, those two constructors have indeed been a single one:
basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
// ~~~~
const Allocator& a = Allocator());
But this has been changed to the current version with two separate constructors due to LWG 42.
As far as I know, an implementation of the C++ Standard Library is allowed to merge those two constructors into a single one, which then becomes a copy constructor:
basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
// ~~~~
const Allocator& a = Allocator());
This has different behaviour. As explained in LWG 42 (see Shafik Yaghmour's answer), the actual copy ctor of basic_string
acquires a copy of str
's allocator, whereas the "substring" constructor by default uses a value-initialized new object.
Thanks to Sebastian Redl for pointing that out.
回答2:
So the "old", going back to 1998 specification is very similar to one from the original SO answer the OP points to and has changed at least once to what we have today.
The 1998 specification can be found referenced in LWG issue 42: String ctors specify wrong default allocator:
The basic_string<> copy constructor:
basic_string(const basic_string& str, size_type pos = 0, size_type n = npos, const Allocator& a = Allocator());
specifies an Allocator argument default value that is counter-intuitive. The natural choice for a the allocator to copy from is str.get_allocator(). Though this cannot be expressed in default-argument notation, overloading suffices.
and proposes these possible fixes:
B. In 21.3 [lib.basic.string], and also in 21.3.1 [lib.string.cons], replace the declaration of the copy constructor as follows:
basic_string(const basic_string& str, size_type pos = 0, size_type n = npos);
C. In 21.3 [lib.basic.string], replace the declaration of the copy constructor as follows:
basic_string(const basic_string& str); basic_string(const basic_string& str, size_type pos, size_type n = npos, const Allocator& a = Allocator());
In 21.3.1 [lib.string.cons], replace the copy constructor declaration as above. Add to paragraph 5, Effects:
In the first form, the Allocator value used is copied from str.get_allocator().
The first fix matches the original SO answer the OP points to and the second matches what we have today.
This LWG issue is from 1998 which is probably why none of the public drafts available today have any evidence of this. The earliest public draft available N1804
is from 2005. What changes took place between 1998 and 2005 are not clear.
来源:https://stackoverflow.com/questions/32976919/does-basic-string-class-really-have-copy-constructor-that-takes-more-than-one-pa