4

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

struct s;

s const make_s();

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

使用移动操作和右值引用以及以下功能...

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”临时对象?

4

3 回答 3

14

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

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

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

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

右值引用和移动语义背后的整个想法是临时对象是临时的,因此可以在不伤害任何人的情况下对其进行修改。

于 2011-08-21T14:51:41.090 回答
1

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

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

于 2011-08-21T14:28:00.890 回答
-3

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

于 2011-08-21T14:51:50.683 回答