如何从方法中返回参数,未更改,并且没有c ++中的副本?
// This is more or less the desired signature from the caller's point of view
SomeImmutableObject ManipulateIfNecessary(SomeImmutableObject const& existingObject)
{
// Do some work…
// ...
if (manipulationIsNeccessary)
{
// Return a new object with new data etc (preferably without another copy)...
return SomeImmutableObject(...);
}
else
{
// Return the original object intact (but with no further copies!)...
return existingObject;
}
}
一个例子是C#的String.Trim方法。 C#字符串是不可变的,如果Trim不需要做任何工作,则返回对现有字符串的引用,否则返回带有修剪内容的新字符串对象。
如果接近上述方法签名,我将如何在C ++中模仿这种语义?
答案 0 :(得分:2)
您的对象必须是此工作的引用类型。让我们举一个字符串的玩具示例:
class RefString {
public:
RefString() : ref(new std::string()) { }
RefString(const std::string& str) : ref(new std::string(str)) { }
RefString trim_trailing_newline() {
if (ref->back() == '\n') {
return RefString(ref->substr(0, ref->size()-1));
}
return *this;
}
size_t size() { return ref->size(); }
private:
std::shared_ptr<std::string> ref;
};
int main(int argc, char** argv) {
RefString s("test\n");
std::cout << s.size() << "\n";
std::cout << s.trim_trailing_newline().size() << "\n";
return 0;
}
答案 1 :(得分:1)
一个合理的选择是以支持这种方式的方式实现SomeImmutableObject
- 内部作为指向逻辑状态的引用计数智能指针,而在外部它可以提供值语义。 (这可能会使线程代码的使用变得复杂 - 您可能希望阅读写时复制(COW)以及为什么它在实现std::string
时变得不受欢迎。)
如果您仍然坚持使用现有的SomeImmutableObject
实施,那么您无法进行更改,并且您无法使用引用计数的智能指针进行包装,然后选择获取有限的。
它不提供干净的来电者使用,但您可以使manipulationIsNeccessary
成为来电者可访问的功能,然后让来电者使用新数据调用&#34;新对象&#34 ; 代码 - 在第二个函数中:
SomeImmutableObject obj;
const SomeImmutableObject& o =
manipulationIsNecessary(obj) ? newObjectWithNewData(obj) : obj;
...use o...
通过让newObjectWithNewData
成为一个单独的函数,你应该得到返回值优化(虽然它最好用你的编译器/设置检查)。
答案 2 :(得分:1)
你可能总是返回const SomeImmutableObject&amp;。请注意,将结果分配给对象将调用副本。
SomeImmutableObject x = ManipulateIfNecessary(y); // will invoke a copy-ctor
真正的诀窍是实施。当第一个&#34;如果&#34;子句有效,你可能会返回对临时变量的引用(不好的事情)。必须动态分配新创建的对象。
总而言之,我认为没有一些智能内存管理这是不可能的。