cv::String 和 std::string:啥时候使用哪一个以及两者都使用的必要性?

Posted

技术标签:

【中文标题】cv::String 和 std::string:啥时候使用哪一个以及两者都使用的必要性?【英文标题】:cv::String and std::string: When to use which one and necessity to use both?cv::String 和 std::string:什么时候使用哪一个以及两者都使用的必要性? 【发布时间】:2017-08-24 08:00:15 【问题描述】:

在 OpenCV 项目中,cv::String 通常用于函数中,例如一个简单的putText。但是,在使用std 的功能时,std::string 负责。例如。在这种情况下

ifstream stream(filepath);
string line;
getline(stream, line, '\n');

必须有一个std::string,因为cv::String 会引发错误。在反之亦然的情况下,使用 OpenCV 函数 std::string 被正确转换为 cv::String 并且以下代码确实有效:

string Str = "Test";
putText(img, Str, Point(10, 10), FONT_HERSHEY_PLAIN, 1, Scalar::all(255), 1);

问题

为什么 OpenCV 有自己的 String-Class?我认为可能存在一些对 OpenCV 有用的差异,而 std::string 的所有(或大部分?)功能仍然适用于 cv::String。但似乎std::string 可以转换为cv::String(我至少测试过putText

文档显示了类似的功能,但也有一些差异,例如相关功能static bool operator> (const String &lhs, const String &rhs) 和类似功能:

http://docs.opencv.org/3.1.0/d1/d8f/classcv_1_1String.htmlcv::String http://www.cplusplus.com/reference/string/string/ 为std::string

我错过了什么吗?

我是否有理由在一个项目中同时使用两个版本的字符串,或者仅使用std::string 以提高可读性是可以接受的? (只要不使用例如前面提到的相关功能)

编辑: 这个问题here 解决了与QString 和字符串类似的问题,建议尽可能使用std::string。我想知道这对 OpenCV 是否也有效。

【问题讨论】:

【参考方案1】:

为什么 OpenCV 有自己的字符串类? OpenCV 是一个相当古老的库(2000 年 6 月首次发布)。那时,标准库不太可靠,OpenCV 团队可能决定他们宁愿自己编写。几年前,MFC 团队做出了同样的决定,Qt 团队和 wxWidgets 团队也是如此。这种“字符串”类的激增正是标准委员会定义std::string 的原因——但为时已晚。

如果您可以在整个项目中只使用一个字符串类就可以逃脱 - 去吧。通常你不能;例如,给定一个返回cv::String 的函数,不会自动转换为std::string 给定一个通过非常量引用获取cv::String 的函数,你需要一个实际的@ 987654327@ 要传递的对象。 (编辑:Jonas 指出cv::Stringstd::string 的自动转换。)

另请注意,您对putString 的调用实际上可能使用cv::String - 它是通过转换构造函数从std::string 隐式构造的。如果(且仅当)你有一个性能热点,那些不必要的转换可能是个问题。

【讨论】:

注意cv::Stringoperator std::string() const;,来自:github.com/opencv/opencv/blob/master/modules/core/include/… opencv 的时代可能真的很重要,尤其是因为最初的 openCV 战争纯 C! @Jonas:谢谢!我在查看的文档中错过了这一点。 好吧,从 C++17 开始,您永远不应该使用常量字符串引用作为参数,无论您使用什么字符串类型。相反,它应该是 std::string_view 值。 @Deduplicator:C++17 还不是官方的 ISO 标准。 ...而且我敢打赌 OpenCV 不会改变它们的函数签名。 (尽管如果他们添加另一个并将其余部分内联转发给它会很好。)【参考方案2】:

如果您知道自己构造了一个字符串以仅将其与 openCV 函数一起使用,并且您不需要以花哨的方式对其进行操作,那么我将使用 cv::String 来避免多次转换并尽可能减少在项目。

另一方面,如果您计划在您的应用程序中使用您的字符串,或者您计划在将它传递给函数之前使用它,我会坚持使用std::string,因为它带有所有算法您可以使用它的标准库,并且再次避免多次转换。

对我来说,如果方便的话,可以在同一个应用程序的不同部分同时使用这两个版本。只要对它们的使用保持一致,例如如果您选择上述方法,请不要使用 std::string 如果其唯一目的是提供 openCV 功能,反之亦然。

至于为什么 openCV 开发人员决定拥有自己的字符串版本,我只能猜测,我猜他们认为即使今天基本功能相同,拥有自己的版本也为引入新的明天不会破坏现有代码的功能。将其他类包装在您自己的内部是一种相当常见的设计方法,尤其是在您编写库时,即使您的类最初不提供额外的功能 - 只是为了让门敞开,以防您有一天想使用不同的库自己实现一些功能或添加新功能。

【讨论】:

【参考方案3】:

changelog of OpenCV 4.0 声明:

感谢扩展的 C++11 标准库,我们可以摆脱手工制作的 cv::Stringcv::Ptr。现在cv::String == std::stringcv::Ptrstd::shared_ptr 之上的薄包装。

【讨论】:

以上是关于cv::String 和 std::string:啥时候使用哪一个以及两者都使用的必要性?的主要内容,如果未能解决你的问题,请参考以下文章

创建 boost::tuple<std::string, std::string, int> 和 std::vector<int> 的映射

如何将CString和:: std :: string :: std :: wstring互相转换?

Cython C++ 和 std::string

为啥 g++ 不关心初始化列表分配给 (const std::string&) a (std::string)?和其他怪异[关闭]

cpp中std::string和std::wstring 相互转换

std::string 和 std::vector<char> 有啥区别?