为什么在返回右值引用时给出C ++编译器警告? [英] Why give a C++ compiler warning when returning an rvalue reference?

查看:1459
本文介绍了为什么在返回右值引用时给出C ++编译器警告?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究右值引用(对我来说是一个新概念),并且在下面的类函数中收到一个警告令我感到困惑...

I've been studying rvalue references (a new concept for me), and am puzzled by a warning I receive in the following class function...

string&& Sampler::Serial() const {
    stringstream ss;
    .
    . [assemble a string value using data members]
    .
    return ss.str();
}

此编译成功,但出现以下警告...

This compiles successfully, but with the following warning...

..\Metrics\Sampler.cpp:71:16: warning: returning reference to temporary [-Wreturn-local-addr]
  return ss.str();
                ^

我完全知道我要返回一个临时事实上,我使用右值引用作为我的返回类型。

I'm fully aware that I'm returning a temporary, as evidenced by the fact that I'm using an rvalue reference as my return type. The code seems to run fine upon execution, so why should this warrant a compiler warning?

类似问题似乎是复制返回值而不是使用引用,但为什么我应该复制潜在的大量临时数据当我可以移动它与右值引用?这不是为什么它被发明了吗?

The standard answer to similar questions seems to be to copy the return value instead of using a reference, but why should I copy potentially massive amounts of temporary data when I can move it with an rvalue reference? Isn't that why it was invented?

推荐答案

您不是移动数据。您正在创建一个本地对象,创建对该本地对象的引用,销毁该本地对象,然后仍然使用该引用。

You're not moving your data. You're creating a local object, creating a reference to that local object, destroying that local object, and then still using that reference.

您应该返回值你已经找到了。但是不是复制,而是移动数据。这是确保您不复制这些大量数据的安全方法。

You should return by value, as you already found. But instead of copying, move the data. That's the safe way of ensuring you don't copy those massive amounts of data.

std::string Sampler::Serial() const {
    std::stringstream ss;
    .
    . [assemble a string value using data members]
    .
    return std::move(ss.str());
}

注意: std :: move 在这里是技术上多余的,因为 ss.str()已经返回一个右值,因此已经被移动。我建议离开它。这种方式适用于任何情况,所以你不必考虑使用哪种形式:如果你想移动,写 move

Note: the std::move is technically redundant here, as ss.str() already returns an rvalue and so would already be moved. I recommend leaving it in anyway. This way works in any situation, so you don't have to think about which form to use: if you want to move, write move.

正如TC所指出的,一般来说,尽管不是在你的情况下,这可以防止RVO。在RVO可能并且编译器将隐式地使用移动的情况下,不需要显式地写 move 。例如:

As pointed out by T.C., in general, though not in your case, this can prevent RVO. In cases where RVO is possible and where the compiler would implicitly use a move anyway, there is no need to write move explicitly. For instance:

std::string f() {
  std::string x;
  ...
  return x; // not std::move(x)
}

向读者清楚, x 是一个局部变量。 C ++代码返回局部变量而不编写 move 是正常的,因为编译器会清除局部变量的 x 并直接在返回槽中构造 std :: string 对象(无论对你的平台意味着什么),否则编译器将使用 std :: string 隐式。

Here, it should already be clear to the reader that x is a local variable. It's normal for C++ code to return local variables without writing move, because either the compiler will elide the x local variable entirely and construct the std::string object directly in the return slot (whatever that means for your platform), or the compiler will use the move constructor of std::string implicitly anyway.

这篇关于为什么在返回右值引用时给出C ++编译器警告?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆