左值的 C++ std::move() 性能明智
Posted
技术标签:
【中文标题】左值的 C++ std::move() 性能明智【英文标题】:C++ std::move() performance wise with lvalues 【发布时间】:2020-11-10 21:16:03 【问题描述】:我刚刚学习完左值、右值、移动构造函数和移动运算符。 我可以看到使用具有 rvalues 性能和可用性的移动构造函数的附加值。 但是我看不到使用带有 lvalues 性能的 move 构造函数的附加值,肯定有附加值可用性,但是我们不能使用一些实现 lvalues 相同的功能其他技术,例如指针。 所以我的问题是:使用带有 lvalues 性能的移动构造函数的移动运算符的附加值是什么。 感谢您阅读我的问题。
示例:
class string
public:
char* data;
string()
data = nullptr;
string(const char* p)
size_t size = std::strlen(p) + 1;
data = new char[size];
std::memcpy(data, p, size);
~string()
delete[] data;
string(const string& that)
size_t size = std::strlen(that.data) + 1;
data = new char[size];
std::memcpy(data, that.data, size);
string(string&& that)
data = that.data;
that.data = nullptr;
string movee(string &that)
data = that.data;
that.data = nullptr;
;
在性能方面有什么不同:
string s1("test");
string s2(std::move(s1));
string s1("test");
string s2 = string();
s2.movee(s1);
在右值的情况下,编译器为我们节省了时间和内存来重新构造一个新对象并将右值分配给它,然后使用该新对象更改移动到对象中的值,从而提高性能.但是在左值对象的情况下,移动操作符并没有提高性能,它当然是提高可用性和可读性,但它并没有像右值一样提高性能,我错了吗?
【问题讨论】:
std::move
只是告诉编译器:“可以将此左值视为右值,并窃取其内容;我不打算以后使用它”。因此,现有的右值机制也可以应用于这个左值。为左值发明一种全新的、独立的机器,而不是重用已经存在于右值的机器,有什么意义?
感谢您的回答,我可以看到易用性,但我的问题是考虑性能
您可以使用其他技术归档大多数内容。但是在语言的核心中添加一个标准化的功能可以使它得到很好的定义,并且理想地允许编译器做得更好,允许静态分析器警告你错误,并提高可维护性。
考虑什么的性能,与其他什么相比?
附加值和一般一样,你移动而不是复制。移动语义可以在没有语言支持的情况下实现,但它相当具有侵入性,因此在语言支持时使用“其他技术”并不是很理想
【参考方案1】:
您可以使用指针间接实现相同的功能。事实上,我们曾经,甚至现在,这正是发生在您的移动构造函数/赋值运算符内部的情况!
是的,std::move
变量的大部分好处在于代码的简洁性。但这并非毫无意义。使用移动构造函数/赋值运算符窃取资源使我们能够巧妙、快速地完成此操作,而不会受到任何黑客攻击或任何性能损失。您的代码将更易于维护且更易于合理化。您将不太想添加一个额外的间接层,动态分配不需要动态分配的东西,只是为了获得任何可以理解的代码,因为现在不会有任何 em> 这样做会受益。
但是!不要忘记您的标准容器在幕后为您执行此操作,例如当std::vector
调整大小时。这是非常有价值的。如果我们只能从临时人员那里搬走,那将是不可能的,我们将浪费大量机会。
用临时工做这件事并没有什么不同;只是它为您完成,无需输入std::move
。
【讨论】:
感谢您的回答,它提供了很多信息,但您在最后的陈述中是什么意思 @ColdHands 您说您已经看到了从“右值”迁移的好处。我是说“左值”的好处并没有什么不同。它只是在您的代码中拼写不同(并且使用较少)。 你确定用右值做和用左值做是一样的吗,用右值做的时候会有很多优化,但是除了可读性和可用性之外,两者之间有什么区别吗?movee
和移动构造函数?
@ColdHands “将它与右值一起使用时会发生更多的优化”你能为我命名一个吗?
@ColdHands "movee 和 move 构造函数有什么区别吗?" 这是一个错误的比较。 std::move
是一个实用程序,可让您访问移动构造函数。这就像在问奶牛和农场之间的区别。以上是关于左值的 C++ std::move() 性能明智的主要内容,如果未能解决你的问题,请参考以下文章
C++ std::move()函数(将一个左值强制转化为右值引用,继而可以通过右值引用使用该值)