basic_string class 是否真的有接受多个参数的复制构造函数,或者它只是构造函数?

Does basic_string class really have copy constructor that takes more than one parameter or is it just constructor?

我正在阅读 Why would a copy constructor have more than one parameter?

接受的答案是:

旧的 std::basic_string 也有一个:

basic_string(const basic_string& s, 
         size_type pos = 0, size_type n = npos)

但是 http://www.cplusplus.com/reference/string/basic_string/basic_string/ 说:

basic_string (const basic_string& str, size_type pos, size_type len = npos,
              const allocator_type& alloc = allocator_type());

以上不是复制构造函数,而是复制 str 从字符位置 pos 开始并跨越 len 个字符的部分的子字符串构造函数。

C++ 标准部分说:

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

那么,link 接受的答案是错误的吗?这真的是 basic_string class 子字符串的构造函数吗?我已经在 link 上的 C++98、C++11 和 C++14 规范中检查了原型,所有显示都相同。

(前)C++11 国际标准 [basic.string]p5 中 basic_string class 模板的规范包含以下两个构造函数(以及其他构造函数):

basic_string(const basic_string& str);
// ...
basic_string(const basic_string& str, size_type pos, size_type n = npos,
             const Allocator& a = Allocator());

第一个明明是拷贝构造函数,第二个不是拷贝构造函数。请注意,规范中没有 no 构造函数,其中 pos 具有默认参数。

C++03、C++14和C++1z的情况基本相同。在 C++98 中,这两个构造函数确实是一个构造函数:

 basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
 //                                                 ~~~~
              const Allocator& a = Allocator());

但由于 LWG 42.

,这已更改为具有两个独立构造函数的当前版本

据我所知,允许 C++ 标准库的实现将这两个构造函数合并为一个构造函数,然后成为一个 复制构造函数 :

 basic_string(const basic_string& str, size_type pos = 0, size_type n = npos,
 //                                                 ~~~~
              const Allocator& a = Allocator());

这有不同的行为。正如 LWG 42 中所解释的(参见 Shafik Yaghmour's ),basic_string 的实际复制构造函数获取了 str 分配器的副本,而 "substring" 构造函数默认使用一个值-初始化新对象。

感谢 Sebastian Redl 指出这一点。

所以 "old",追溯到 1998 年的规范与 original SO answer the OP points to 中的规范非常相似,并且至少更改了一次今天。

可在 LWG issue 42: String ctors specify wrong default allocator:

中找到引用的 1998 规范

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.

并提出以下可能的修复方法:

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().

第一个修复与 original SO answer the OP points to 相匹配,第二个与我们今天所拥有的相匹配。

这个 LWG 问题是从 1998 年开始的,这可能就是为什么今天可用的 public 草稿中的 none 有任何证据表明这一点。最早的 public 可用草案 N1804 是 2005 年的。1998 年和 2005 年之间发生了什么变化尚不清楚。