简体   繁体   English

返回const值,防止移动语义

[英]return const value prevent move semantics

I am a beginner in cpp so excuse me for this question. 我是cpp的初学者,请问这个问题。

I was reading that returning const val prevents move semantics. 我在读,返回const val可以防止移动语义。 therefore I dont understand why the following code is compiled and works normally. 因此,我不明白为什么以下代码会被编译并正常工作。 is it because only temporary object is being created? 是因为仅创建了临时对象? in what cases the move semantics cannot being done? 在什么情况下无法完成移动语义? thank you in advance! 先感谢您!

#include <iostream>
using namespace std;

const string foo()
{
    return string("hello");
}

int main()
{
    string other = std::move(foo());
}

I was reading that returning const val prevents move semantics. 我在读,返回const val可以防止移动语义。 therefore I dont understand why the following code is compiled and works normally. 因此,我不明白为什么以下代码会被编译并正常工作。

When move semantics are prevented by some mechanism, this doesn't necessarily mean that the code doesn't compile. 当通过某种机制阻止了移动语义时,这并不一定意味着代码不会编译。 Often, it compiles happily, but an expected move construction turns out to be a copy instead. 通常,它会很高兴地进行编译,但是预期的动作构造却是副本。

Example: a type has a user provided copy ctor, which disables compiler-generated move ctors. 示例:某个类型具有用户提供的复制ctor,它将禁用编译器生成的移动ctor。 When we think we move-construct, we don't. 当我们认为我们进行移动构建时,我们不会。

struct Test {
   Test() = default;
   Test(const Test&) {}
};

Test t1;
Test t2{std::move(t1)}; // Copies!

in what cases the move semantics cannot being done? 在什么情况下无法完成移动语义?

Coming to your example, something that is const -qualified can't be used to move-construct another object in any meaningful way. 以您的示例为例,不能使用const限定的东西以任何有意义的方式移动构造另一个对象。 Move construction makes sense when resources can be easily transferred, but const -ness prevents that. 当可以轻松转移资源时,移动构造很有意义,但是const -ness可以防止这种情况。 Example: a type has compiler-generate move and copy constructors, but we can't move-construct from a const instance. 示例:一个类型具有编译器生成的move和copy构造函数,但是我们不能从const实例进行move-construct。

struct Test {
    Test() = default;
};

const Test t1;
Test t2{std::move(t1)};  // Copies!

Besides, it doesn't make sense to move something that is returned by a function by value: 此外,按值移动函数返回的内容没有意义:

string other = std::move(foo());

When foo() returns by value, you can move-construct from it, unless the return type is const . foo()按值返回时,您可以从中进行移动构造,除非返回类型为const Hence, to enable move-construction of other : 因此,要启用other移动构造:

std::string foo();

string other = foo();

std::move is just a unconditional cast to rvalue. std::move只是对rvalue的无条件强制转换。 In your case the return value of std::move(foo()) was const std::string&& . 在您的情况下, std::move(foo())的返回值为const std::string&& And because move constructor does not take const argument, copy constructor was called instead. 而且由于move构造函数不采用const参数,因此调用了复制构造函数。

struct C {
    C() { std::cout << "constructor" << std::endl; }
    C(const C& other) { std::cout << "copy constructor" << std::endl; }
    C(C&& other) { std::cout << "move constructor" << std::endl; }
};

const C get() {
    return C();
}

int main() {
    C c(std::move(get()));
    return 0;
}

std::move doesn't actually move anything. std::move实际上并没有移动任何东西。 It is just an "rvalue cast". 这只是一个“右值强制转换”。 You cast something to rvalue, and the move constructor / move assignment operator does the actual moving if possible . 您将某些内容强制转换为rvalue,并且move构造器/ move赋值运算符在可能的情况下进行实际的移动。 "If possible" part is the key. “如果可能”部分是关键。 In your example the return value is already an rvalue, so std::move literally does nothing. 在您的示例中,返回值已经是一个右值,因此std::move实际上不执行任何操作。 You may even get warnings like "nothing is moved". 您甚至可能会收到“什么都没有动”之类的警告。 That is because the move constructor of std::string takes an argument of type std::string&& not const std::string&& . 这是因为std::string的move构造函数采用的类型为std::string&&而不是const std::string&& Because of that, the copy constructor is called. 因此,将调用复制构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM