我在Qt's Doc中找到了这个:
QStringViews应该通过值传递,而不是通过引用常量传递:
,并给出以下示例:
void myfun1(QStringView sv); // preferred
void myfun2(const QStringView &sv); // compiles and works, but slower
这怎么可能?
答案 0 :(得分:3)
他们在文档中说应该按值传递,因为QStringView
本身并不是字符串,它只是一种接口(嗯,这就是为什么它被称为“视图”的原因),它为您提供了读取对引用字符串的访问。因此,QStringView
的大小很可能类似于参考的大小。根据QT源代码,QStringView
只有2个字段:
private:
qsizetype m_size;
const storage_type *m_data;
在装有gcc 6.3的Debian9 x64机器上,此类的大小为8(指针)+ 4(整数)= 12个字节。在我的情况下,参考大小是8个字节,因此,在函数调用上的数据复制方面只有很小的差异。请记住,在不同的计算机上引用可能以另一种方式实现,并且可能更大。
虽然我同意这种接口应该通过副本传递(而不是const ref),但我不明白为什么他们声称通过const ref传递它实际上更慢(两次对变量进行解引用实际上并没有在现代应用中的任何可观察到的效果)。我真的很想看看支持该说法的测试。
答案 1 :(得分:2)
QStringView
通常用于高性能代码中,由于涉及的内存分配,创建实际的QString
对象会很慢。我优化了QStringView
,使其性能与手动处理(const QChar*, size_t)
一样。我什至花了很多时间让成员函数调用内联传递到自由函数,并按值传递*this
。所有这些都是为了避免将QStringView
个对象强制放入堆栈,或更一般地说,将其强制放入内存。
在几乎所有C ++编译器中,QStringView
对象都表示为一对CPU寄存器,并且许多C ++ ABI(不幸的是,不包括Windows)都支持将此类类型的CPU寄存器传递给函数。如果您天真地编写了成员函数,并使用一个隐式this
参数作为对象的 address ,则离线调用此类函数将迫使编译器分配一个{{1 }}对象可以使其地址作为成员函数的第一个参数传递。
传递值还有第二个参数:别名问题较少。作为参考类型,QStringView
仍然存在该问题,但请考虑QStringView
:接受
std::complex
(为简洁起见,省略了模板args)。可以这样称呼:
std::complex &operator*=(std::complex &lhs, const std::complex &rhs);
如果您天真地将std::complex c = 3 + 4i;
c *= c;
当作数学函数来实现:
operator*=
在第一行之后,您本该auto r = real(), i = imag();
m_real = r * other.real() - i * other.imag();
m_imag = r * other.imag() + i * other.real();
蒙上阴影,从而计算出错误的结果(是的,人们 do 在生产中编写了此代码)。按值传递other.real()
可以解决问题。