【问题标题】:C++ Passing a long string to constructor or setterC ++将长字符串传递给构造函数或setter
【发布时间】:2013-01-27 23:47:00
【问题描述】:

我有一个带有 Glib::ustring 成员的类(如果你不熟悉它,假设它是 std::string),它应该包含一个长字符串,即至少一个段落,可能还有更多.甚至可能超过 10 段。该字符串计划在 GUI 中显示,因此将来可能会将其存储在文本小部件的缓冲区中,但现在它只是我的 C++ 类的字符串成员对象。

问题是:如何将字符串传递给构造函数,以及如何将其传递给set_string() setter方法。长字符串意味着大副本,所以我认为一个好的解决方案是采用右值引用并将 std::move 参数放入成员对象中。但我也不希望类接口令人惊讶且难以使用/理解。你知道,最不意外的规则。

所以我在想,在这种情况下,预期/常见的解决方案是什么?

(对于setter方法,这里还有一个选择:因为编辑是在GUI中完成的,所以让GUI直接编辑字符串,然后setter方法的唯一用途就是以编程方式完全替换字符串,例如重置或撤消最近的编辑)

class MyClass
{
public:
     explicit MyClass (Glib::ustring str);
     void set_string (Glib::ustring str);
private:
     Glib::ustring str;
}

(我已经看到现有库的代码,例如 gtkmm,通过 const 引用获取字符串,但我也看到 SO 帖子的答案是按值传递以允许优化)

【问题讨论】:

  • 通过引用传递字符串。
  • @Aeluned 不好的建议:如果要复制它,请传递 value。然后move 出复制的参数。让编译器在调用视线处进行复制,而不是将其隐藏在方法的主体中,这样就可以使用 copy-in-body 版本所缺少的优化。

标签: c++ c++11 parameter-passing glib stdstring


【解决方案1】:

我会去找参考资料(不仅要传递它们,还要存储参考资料)。但是,二传手必须重新安装参考,这是不可能的。如果你真的需要在构造后更改字符串,你必须使用指针(可能是智能指针)。

根据周围的代码,您可能希望使用字符串的共享所有权。在这种情况下,我会使用std::shared_pointer<GLib::ustring>如果你需要一个二传手。 (否则,参考更好。)

请注意,“某些段落”不是很长的字符串。在用户界面中,几毫秒的延迟,比如说在加载一些文本文件时,是完全可以接受的。与往常一样:请先分析您的代码,检测瓶颈,然后在需要时进行优化以提高速度。

【讨论】:

  • 当然,我只是想在使用界面之前做出设计决定。 (现在更容易做出明智的决定,而不是稍后加载一个长文本文件并意识到我需要更改界面并可能破坏现有代码)
【解决方案2】:

http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/

假设您的 string 具有高效的移动构造函数,您的函数应该按值获取 string

当您期望字符串很长时,调用者调用std::move 并将值传递给setter/constructor。这并不奇怪,因为std::move 非常明确地表明您正在移动数据。

如果您的系统的并发量不多,并且您很少修改字符串(实际上,大多数字符串的共享次数远多于修改次数),那么共享指向不可变字符串的指针实际上是一种非常有用的模式。 (共享的写数据是引用计数,所以高并发会引起争用)

【讨论】:

  • 但是如果我想允许 std::move 我需要编写一个构造函数来接受 std::string&& 参数,对吧?然后调用者可以通过 std::move(my_str)
  • 不,你可以只取一个带有string的构造函数,然后如果你std::move它被移动到那个参数中,如果你不std::move它被复制到那个参数。这个想法是在参数传递时进行可能的复制。
  • 那么我还有一个问题:为什么构造函数(或任何其他函数)需要使用右值引用参数?
  • 没有右值引用,move 不能高效。实际上,您正在将高效 move 的工作传递给类本身(具有右值引用 move 构造函数),而不是复制它(通过拥有自己的右值引用 move 参数)。海龟不会一路往下走,但是你写的代码通常可以骑着海龟。
  • std::move 无论如何都不会在没有班级支持的情况下做任何事情。在某些情况下,这种支持可能是被动的,但在这里可能不是。如果支持,您可以使用 rvalue ref 尝试交换。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多