赞赏良好的链接.
在我的 Fedora 34 环境(g++)中,std::accumulate定义为:
template<typename ITER, typename T>
constexpr inline T accumulate(ITER first, ITER last, T init)
{
for (; first != last; ++first)
init = std::move(init) + *first; // why move ?
return init;
}
Run Code Online (Sandbox Code Playgroud)
如果表达式init + *first已经是右值,那么 的目的是什么std::move?
有人能解释一下这段代码的执行顺序吗?
struct Foo {
~Foo() {
std::cout << "1";
}
};
Run Code Online (Sandbox Code Playgroud)
int main() {
const Foo& bar = Foo();
const Foo& baz = std::move(Foo());
std::cout << "2";
}
Run Code Online (Sandbox Code Playgroud)
以下代码打印121.
我明白为什么我在 2 之后得到 1,这是因为对象的生命周期绑定到它执行的代码块,而且我也知道右值可以绑定到左值 const 引用,但是为什么立即调用移动对象的析构函数?这是什么原因呢?这个析构函数到底在哪里被调用?
在以下代码段中:
std::vector<double> a(100, 4.2);
auto* a_ptr = a.data();
auto b = std::move(a);
auto* b_ptr = b.data();
std::cout << ((b_ptr == a_ptr) ? "TRUE" : "FALSE") << '\n';
Run Code Online (Sandbox Code Playgroud)
C++标准保证b_ptr总是等于a_ptr后std::move?在wandbox打印上运行代码TRUE.
一篇C++ Next博客文章说
A compute(…)
{
A v;
…
return v;
}
Run Code Online (Sandbox Code Playgroud)
如果A具有可访问的副本或移动构造函数,则编译器可以选择忽略该副本.否则,如果A有移动构造函数,v则移动.否则,如果A有复制构造函数,v则复制.否则,将发出编译时错误.
我以为我应该总是返回值,std::move
因为编译器能够找出用户的最佳选择.但另一个例子来自博客文章
Matrix operator+(Matrix&& temp, Matrix&& y)
{ temp += y; return std::move(temp); }
Run Code Online (Sandbox Code Playgroud)
这std::move是必要的,因为y必须将其视为函数内的左值.
啊,在研究这篇博文之后,我的脑袋几乎爆炸了.我尽力去理解推理,但是我学的越多,我就越困惑.我们为什么要借助于这个价值来回报这个价值std::move?
I was reading this post.
And I reached to the following code.
I was wondering:
Is std::move useful for strings (assuming the string is long enough)?
Does it invalidate the previous string?
Where should I use it and where I should not?
.
class Name
{
public:
Name(std::string firstName, std::string lastName)
: firstName_(std::move(firstName))
, lastName_(std::move(lastName)) {}
void print() const
{
std::cout << lastName_ << ", " << firstName_ << '\n';
}
private:
std::string firstName_;
std::string lastName_;
};
Run Code Online (Sandbox Code Playgroud)
My technique …
在std::move对象上调用之后,如果在之后使用该对象,为什么语言不会导致编译错误?
是因为编译器无法检测到这种情况吗?
为什么下面的代码片段是合法的 C++ 代码?这是一个纯粹的理论问题 - 我没有想到任何用例:
#include <optional>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v{1, 2, 3};
const std::optional<std::vector<int>> ov = v;
const auto nv = std::move(ov.value());
for (const auto& x : *ov) { std::cout << x; }
for (const auto& x : nv) { std::cout << x; }
}
Run Code Online (Sandbox Code Playgroud)
这产生了123123,但我不明白原因。
std::move应用于 a 的值const optional?optional ov仍然持有vector?是否ov.value()在内部创建一个临时副本,然后从中移动?
说我有以下功能
void doWork(Widget && param) // param is an LVALUE of RRef type
{
Widget store = std::move(param);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要param回到rvalue std::move()?是不是很明显,paramrvalue 的类型是因为它在函数签名中被声明为右值引用?不应该仅仅根据这个原则自动调用移动构造函数吗?
为什么不默认发生这种情况?
c++ rvalue-reference move-constructor lvalue-to-rvalue stdmove
我对std::move()在下面的代码中使用感到困惑:
如果我在 (2) 处取消注释行,输出将是:1 2 3但如果我在 (1) 处取消注释行,输出将什么都不是,这意味着std::vector调用了移动构造函数!
为什么我们必须再次调用std::moveat (1) 来调用移动构造函数std::vector?
我的理解是std::move得到r-value其参数的话,为什么我们要得到r-value的r-value在(1)?
我认为_v = rv;(2) 中的这一行更合乎逻辑,应该使std::vector移动构造函数不被调用,std::move因为rv它首先是r-value引用。
template <class T>
class A
{
public:
void set(std::vector<T> & lv)
{
}
void set(std::vector<T> && rv)
{
//_v = std::move(rv); (1)
//_v = rv; (2)
}
private:
std::vector<T> _v;
};
int main()
{
std::vector<int> vec{1,2,3}; …Run Code Online (Sandbox Code Playgroud) c++ ×10
stdmove ×10
c++11 ×4
c++-faq ×1
c++14 ×1
compilation ×1
destructor ×1
lifetime ×1
move ×1
return ×1
stdoptional ×1
vector ×1