【问题标题】:Does basic_string class really have copy constructor that takes more than one parameter or is it just constructor?basic_string 类真的有带多个参数的复制构造函数还是只是构造函数?
【发布时间】:2015-10-06 18:20:13
【问题描述】:

我正在阅读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++ 标准部分说:

类 X 的非模板构造函数是一个复制构造函数,如果它 第一个参数的类型为 X&、const X&、volatile X& 或 const volatile X&,或者没有其他参数,或者其他所有参数 参数有默认参数

那么,该链接中接受的答案是否不正确?这真的是用于子字符串的 basic_string 类构造函数吗?我已经在链接上的 C++98、C++11 和 C++14 规范中检查了原型,所有显示都相同。

【问题讨论】:

  • @Downvoters:养成一种习惯,指定拒绝投票的原因。为什么要投反对票?
  • @owacoder:我认为这是对的。但是Brian Bi说quora.com/…不是复制构造函数。
  • 对不起,我错了,我没有仔细阅读。我会在 Quora 上删除我的答案。
  • @PravasiMeet "Copy-constructor" 在 C++ 法律术语中具有特定含义。该构造函数是一个复制构造函数,因为它满足您引用的要求。它也可以被描述为一个子字符串构造函数(它不是一个 C++ 标准术语)来传达与它可以做的额外事情相关的额外含义。
  • @dyp - 是的,documentation 声称它没有默认的第二个参数,在这种情况下,它将 not 是一个复制构造函数,但引用的接受的答案声称它是。唔。谁是对的?

标签: c++ string parameters copy-constructor stdstring


【解决方案1】:

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

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'sanswer),basic_string 的实际复制 ctor 获取了str 分配器的副本,而“子字符串”构造函数默认使用值初始化的新对象。

感谢Sebastian Redl 指出这一点。

【讨论】:

  • 我的立场是正确的。我忽略了“无默认参数”部分。在这里,投赞成票。
  • "C++ 标准库的实现允许将这两个构造函数合并为一个" 这只是因为用户代码无法检测到这一点,对吧?
  • @Brian 这是我的推理,是的。然后,我尝试查找 [conforming] 关于该案例的内容,但我不确定是否已涵盖。有 [member.functions] 不允许合并但允许拆分;但我不确定它是否也适用于构造函数。
  • 如果实现要合并两个构造函数,则副本不会复制源的分配器,它会从默认参数中获取默认构造的分配器。
  • @SebastianRedl 啊,对,我应该在阅读 Shafik 的文章后修改我的答案。
【解决方案2】:

所以“旧”,追溯到 1998 年的规范与 original SO answer the OP points to 中的规范非常相似,并且至少改变了一次到我们今天的规范。

可以在LWG issue 42: String ctors specify wrong default allocator 中找到 1998 年的规范:

basic_string 复制构造函数:

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

指定分配器参数的默认值是 反直觉。分配器复制的自然选择 是 str.get_allocator()。虽然这不能表达为 默认参数表示法,重载就足够了。

并提出这些可能的修复:

B.在 21.3 [lib.basic.string] 和 21.3.1 [lib.string.cons] 中, 将复制构造函数的声明替换为:

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

C.在 21.3 [lib.basic.string] 中,替换副本的声明 构造函数如下:

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

在 21.3.1 [lib.string.cons] 中,替换上面的复制构造函数声明。添加到第 5 段,效果:

在第一种形式中,使用的分配器值是从 str.get_allocator() 复制而来的。

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

这个 LWG 问题是 1998 年的,这可能就是为什么今天可用的公共草稿都没有任何证据的原因。最早的公开草案N1804 是从 2005 年开始的。1998 年到 2005 年之间发生了哪些变化尚不清楚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 1970-01-01
    • 2015-06-15
    • 2021-03-22
    • 2013-10-25
    • 2012-06-30
    • 2016-04-02
    相关资源
    最近更新 更多