C++:不可变方法版本

And*_*s T 2 c++ c++11

在C++ 11中,提供两个版本方法的最佳方法是什么,一个用于修改对象本身,另一个用于返回修改后的副本?

例如,考虑一个具有"append(string)"方法的字符串类.有时您可能希望使用append来修改现有的字符串对象,有时您可能希望保持字符串对象相同并创建副本.

当然,我可以实现第一个版本并在每次需要时手动创建一个新对象,但这会为我的项目添加多个临时变量和代码行.

如果还不清楚我想做什么:

String s1("xy");
String s2 = s1.appendCopy("z");
s1.appendThis("w");
// s1 == "xyw"
// s2 == "xyz"
Run Code Online (Sandbox Code Playgroud)

在Ruby中有一个概念(或者更确切地说,命名约定),对于这样的方法,有两种变体:append(创建一个新的String)并追加!(修改此对象)

C++没有这样的东西,所以我会陷入丑陋的方法名称,如"appendCopy".

有没有一种好方法来实现我想要做的事情?

到目前为止,我最好的想法是使修改版本的类成员和复制/不可变版本的静态方法使对象作为const参数工作.

Mat*_* M. 8

实际上有一个指南,由Herb Sutter在GotW#84中表达:

喜欢非会员非朋友功能.

在您的特定情况下,append(就地)需要修改现有的,string因此非常适合作为类方法,而append(复制)则不然,因此(遵循指南)不应该是类方法.

从而:

void std::string::append(std::string const&);

inline std::string append(std::string left, std::string const& right) {
    left.append(right);
    return left;
}
Run Code Online (Sandbox Code Playgroud)

在流行请求之后,这里有两个可用于优化性能的重载.首先是可以重用其参数缓冲区的成员版本:

void std::string::append(std::string&& other) {
    size_t const result_size = this->size() + other.size();

    if (this->capacity() < result_size) {
        if (other.capacity() >= result_size) {
            swap(*this, other);
            this->prepend(other);
            return;
        }
        // grow buffer
    }

    // append
}
Run Code Online (Sandbox Code Playgroud)

第二个可以重用其右侧缓冲区的自由函数:

inline std::string append(std::string const& left, std::string&& right) {
    right.prepend(left);
    return right;
}
Run Code Online (Sandbox Code Playgroud)

注意:我不确定是否存在不明确的重载.我相信不应该......

  • @dyp我认为`S追加(S,S const&); S追加(S const&,S &&);`在所有情况下都是明确的,并且假设快速移动构造函数接近最优. (2认同)