C++ 移动语义&;返回常量值

C++ 移动语义&;返回常量值,c++,c++11,constants,return-value,move-semantics,C++,C++11,Constants,Return Value,Move Semantics,我有一个习惯(?!?!?)将所有内容作为“常量”值返回。像这样 struct s; s const make_s(); s const &s0 = make_s(); s const s1 = make_s(); make_s().mutating_member_function(); 使用移动操作和r值引用以及以下函数 void take_s(s &&s0); void take_s(s const &&s0); // Doesn't mak

我有一个习惯(?!?!?)将所有内容作为“常量”值返回。像这样

struct s;

s const make_s();

s const &s0 = make_s();
s const s1 = make_s();
make_s().mutating_member_function();
使用移动操作和r值引用以及以下函数

void take_s(s &&s0);
void take_s(s const &&s0);  //  Doesn't make sense
我不能再写了

take_s(make_s());
我开始使用返回常量值的约定的主要原因是为了防止有人编写这样的代码

struct s;

s const make_s();

s const &s0 = make_s();
s const s1 = make_s();
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”应该阻止移动?为什么我们不能移动“const”临时变量?

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


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

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

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

不管它值多少钱,我真的看不出你一开始返回临时警察会得到什么。是的,您阻止人们对其调用变异成员函数,但您为什么要这样做?在最好的情况下,能够这样做是有用的,在最坏的情况下,这是一个容易避免的错误

而你所做的并没有多大意义。临时文件的全部要点是它会在一瞬间消失,所以谁在乎它是否会被修改呢


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

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

我知道这一点,但问题实际上是关于返回常量值。我猜即使使用r值引用,返回常量值也会阻止移动。我以前认为是一个好的实践突然是不正确的。我真的不知道首先返回const值的理由。为什么你会关心阻止人们对返回的对象调用一个变异的成员函数呢?一个常量值返回习惯用法的例子可以在Meyers,“更有效的c++”,1996,第6项中找到。Meyers建议将
const T operator++(int)
作为后缀++的签名。是的。您希望返回常量的唯一情况是,它是指向对象的引用或指针,您不希望调用方能够更改该对象。事实上,返回常量值有助于防止以下错误:if(a*b=c)if a*b的类型可以用c赋值并且可以隐式转换为bool。。。好。这是一种边缘情况,但通过将用户类型返回为const很容易避免。在vc14编译器上测试时,我看到函数返回的常量值仍然被发送到move构造函数。在C++14中是否有新的东西指定了这一点,或者这只是一个特定于编译器的optim?作为一般语句,这是绝对不正确的。也许你可以澄清或提供一个参考,以明确你在谈论什么?