移动语义并返回常量值



我有一个习惯(?!? ? ? ? ?)将所有内容返回为"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

I can not longer write…

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"临时工?

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

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

不管它的价值是什么,我真的不知道你从一开始就返回const临时变量有什么好处。是的,您可以防止人们在其上调用突变成员函数,但是为什么要呢?往好了说,能够这样做是有用的,往坏了说,这是一个很容易避免的错误。

你所做的并没有什么意义。临时的全部意义在于它马上就会消失,所以谁在乎是否被修改呢?

右值引用和移动语义背后的整个思想是临时的,因此它们可以在不伤害任何人的情况下被修改。

你可能会遇到局部变量超出作用域的问题。

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

返回值上的const限定符没有语义意义。如果您在编译器上打开警告级别,则每次您这样做时,它都会发出警告。

最新更新