在 C++11 中,提供方法的两个版本的最佳方式是什么,一种用于修改对象本身,另一种则返回修改后的副本?
例如,考虑一个具有“append(string)”方法的字符串类。有时您可能希望使用追加来修改现有的字符串对象,有时您可能希望保持字符串对象相同并创建一个副本。
当然,我可以只实现第一个版本,并在每次需要时手动创建一个新对象,但这会向我的项目添加多个临时变量和代码行。
如果仍然不清楚我要做什么:
String s1("xy");
String s2 = s1.appendCopy("z");
s1.appendThis("w");
// s1 == "xyw"
// s2 == "xyz"
在 Ruby 中,有一个概念(或者更确切地说,命名约定),它表示此类方法有两种变体:append(创建新字符串)和append! (修改此对象)
C++ 没有这样的东西,所以我会被像“appendCopy”这样丑陋的方法名称所困扰。
有没有好的方法来实现我想做的事情?
到目前为止,我最好的想法是使修改版本类成员和复制/不可变版本静态方法,这些方法将对象作为 const 参数来处理。
实际上有一个指导方针,由 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;
}
根据大众的要求,这里有两个可用于优化性能的重载。首先是可以重用其参数缓冲区的成员版本:
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
}
其次是可以重用其右侧缓冲区的自由函数:
inline std::string append(std::string const& left, std::string&& right) {
right.prepend(left);
return right;
}
注意:我不确定是否存在不明确的重载。我相信不应该有...
使用新的移动语义,您可以编写:
class A{
public:
// this will get the property
const dataType& PropertyName() const { return m_Property; }
// this wil set the property
dataType& PropertyName() { return m_Propery; }
private:
dataType m_Propery;
};
main()
{
A a;
a.PropertyName() = someValueOfType_dataType; // set
someOtherValueOfType_dataType = a.PropertyName(); // get
}
这个问题我想了很多。一是提供该函数的两个版本:可变版本和不可变版本。
例如
class O {
int a = 0;
public:
O() { }
O( const O &o ) : a( o.a ) { }
O& increase() { ++a; return *this; }
O copyIncrease() const {
return O( *this ).increase();
}
};
int main() {
O o;
o.increase();
O o2 = o.copyIncrease();
}
我现在更倾向于的另一个解决方案是不提供不可变的方法,而是提供一个明确请求对象副本的
.copy()
方法。然后,您可以在 .copy()
上运行可变函数
class O {
int a = 0;
public:
O() { }
O( const O &o ) : a( o.a ) { }
inline O copy() const { return *this; }
O& increase() { ++a; return *this; }
};
int main() {
O o;
o.increase();
O o2 = o.copy().increase();
}