移动语义和返回const值

时间:2011-08-21 14:18:31

标签: c++ c++11 const return-value move-semantics

我有习惯(?!?!?)将所有内容作为“const”值返回。像这样......

struct s;

s const make_s();

s const &s0 = make_s();
s const s1 = make_s();

使用移动操作和r值引用以及以下函数...

void take_s(s &&s0);
void take_s(s const &&s0);  //  Doesn't make sense

我再也写不出来了......

take_s(make_s());

我开始使用返回const值的约定的主要原因是为了防止有人编写这样的代码......

make_s().mutating_member_function();

用例如下......

struct c_str_proxy {
    std::string m_s;

    c_str_proxy(std::string &&s) : m_s(std::move(s)) {
    }
};

c_str_proxy c_str(std::string &&s) {
    return c_str_proxy(s);
}

char const * const c_str(std::string const &s) {
    return s.c_str();
}

std::vector < std::string > const &v = make_v();
std::puts(c_str(boost::join(v, ", ")));

std::string const my_join(std::vector < std::string > const &v, char const *sep);

//  THE FOLLOWING WORKS, BUT I THINK THAT IS ACCIDENTAL
//  IT CALLS
//
//      c_str(std::string const &);
//
//  BUT I THINK THE TEMPORARY RETURNED BY
//
//      my_join(v, "; ")
//
//  IS NO LONGER ALIVE BY THE TIME WE ARE INSIDE
//
//      std::puts
//
//  AS WE ARE TAKING THE "c_str()" OF A TEMPORARY "std::string"
//
std::puts(c_str(my_join(v, "; ")));

看起来好像“返回const值”和r值引用在这个特定的用例中没有混合。是吗?

**Edit 0: Extra question...**

无论如何,该对象是暂时的。为什么“const”会阻止移动?为什么我们不能移动“const”临时工?

3 个答案:

答案 0 :(得分:11)

你有两个相互冲突的目标。一方面,您希望阻止对返回的对象进行修改,但另一方面 ,您希望允许进行修改(这就是一个动作)操作是。它通过窃取其内部资源来修改源对象。)

你需要下定决心。您希望对象是不可变的,还是希望人们能够修改它?

对于它的价值,我并不真正看到你通过首先返回const临时值而获得的收益。是的,你阻止人们在其上调用变异成员函数,但你为什么要?充其量,能够这样做是有用的,最坏的情况是,这是一个容易避免的错误。

你正在做的事情并没有多大意义。 临时中的整个点是它会在一瞬间消失,所以如果被修改了

rvalue引用和移动语义背后的整个想法是临时性的临时性,因此可以修改它们而不会伤害任何人。

答案 1 :(得分:1)

您可能实际上遇到了局部变量超出范围的问题。

c_str()返回指向内部缓冲区的指针,因此一旦原始变量超出范围,指针将无效。

答案 2 :(得分:-3)

返回值的const限定符没有语义含义。如果在编译器上调高警告级别,则每次执行此操作时都会发出警告。