显式复制构造函数

Posted

技术标签:

【中文标题】显式复制构造函数【英文标题】:Explicit copy constructor 【发布时间】:2012-07-13 21:33:07 【问题描述】:

我已经扩展了 std::string 以满足我必须将自定义函数构建写入名为 CustomString

的字符串类的需要

我已经定义了构造函数:

    class CustomString : public std::string 
    public:
        explicit CustomString(void);
        explicit CustomString(const std::string& str);
        explicit CustomString(const CustomString& customString);
        //assignment operator
        CustomString& operator=(const CustomString& customString);
    ... ;

在第三个构造函数(拷贝构造函数)和赋值运算符中,其定义为:

CustomString::CustomString(const CustomString& customString):
    std::string(static_cast<std::string>(customString)) 

CustomString& CustomString::operator=(const CustomString& customString)
    this->assign(static_cast<std::string>(customString));
    return *this;

首先,因为这是一个“显式”;意味着需要显式转换才能分配给另一个 CustomString 对象;它在抱怨这项任务。

CustomString s = CustomString("test");

我不确定在哪里明确需要强制转换。

如果复制构造函数不是显式的,代码可以正常工作,但我想知道并实现显式定义,而不是“猜测正确的转换”。

【问题讨论】:

【参考方案1】:

显式拷贝构造函数意味着拷贝构造函数不会被隐式调用,这就是表达式中发生的事情:

CustomString s = CustomString("test");

这个表达式的字面意思是:使用带有const char* 的构造函数创建一个临时的CustomString。隐式调用CustomString 的复制构造函数以从该临时复制到s

现在,如果代码是正确的(即,如果复制构造函数不明确),编译器将通过直接使用字符串文字构造 s 来避免创建临时文件并删除副本。但是编译器仍然必须检查构造是否可以完成并在那里失败。

您可以显式调用复制构造函数:

CustomString s( CustomString("test") );

但我建议您完全避免使用临时的,只需使用 const char* 创建 s

CustomString s( "test" );

无论如何编译器会做什么......

【讨论】:

哦,是的,我完全理解您的答案(这是正确的答案,我已将其标记为最佳答案),但我将如何实现 CustomString s = customStringObjectOnStack; @mkhan3189 当且仅当 copy-ctor 不明确时,您才能实现 CustomString s = customStringObjectOnStack。对于第二个问题,kDelimited 是 CustomString 还是其他?并且 + 你的函数是 const,所以 c.append(static_cast(*this)) 会起作用。 @ForEveR 是的,谢谢。我自己得到了答案。 kDelimiter 是 CustomString 常量对象,是的。 c.append(static_cast&lt;std::string&gt;(*this)) 适用于隐式 copy-ctor 声明。所以一切都很好。该线程可以关闭。 @mkhan3189:您可以通过 CustomString s = customStringObjectOnStack; 来实现 CustomString s = customStringObjectOnStack;,而不是通过 = 语法隐式使用该复制构造函数,而是显式调用复制构造函数:CustomString s( customStringObjectOnStack );【参考方案2】:

从 std::string 派生是不安全的,因为 std::string 没有虚拟析构函数。至于您的问题-您的复制构造函数不应该是明确的,以允许以下用法:

CustomString s = "test";

我也不知道你为什么要将复制构造函数声明为显式的,因为它不是必需的。 仅当您将 CustomString 对象声明为:

CustomString s(CustomString("test"));

【讨论】:

@ildjarn:为什么懒惰?它是正确的(不是最优的,但正确的)解决了问题并提供了解决方案...... @DavidRodríguez-dribeas 当 ildjarn 发表评论时,答案相当短。 谢谢,很好的答案,但这是懒惰的,因为我要求这样做来改进我编写代码的方式,而不是仅仅完成工作。无论如何谢谢:) 只要 OP only 使用CustomStrings 并且不尝试通过std::string 指针deletenew CustomString,就是真的这个推导有什么不安全的地方吗? “只要[...],有什么不安全的吗?”。除非您有办法随着时间的推移可靠且一致地执行条件,包括同事的代码以及将来可能被复制粘贴到的任何地方,否则该问题的答案始终是肯定的。无论“[...]”中有什么。

以上是关于显式复制构造函数的主要内容,如果未能解决你的问题,请参考以下文章

显式复制构造函数

需要使用互斥锁显式定义的复制构造函数

如果类成员是向量,我们是不是应该显式编写复制构造函数?

如果复制列表初始化允许显式构造函数会出现啥问题?

在 C++ 中显式删除移动构造函数的用例 [关闭]

显式默认构造函数