为什么 std::max 通过 const 返回?
Why does std::max return by const&?
我想找到最大Foo
并对其调用inc()
,这是一种非常量方法。 当然,在寻找最大值时,我不想创建任何副本或移动,即我不想Foo foo = std::max(foo1, foo2)
. 我尝试编写自己的max,g++坚持我返回一个const&。
#include <iostream>
class Foo
{
public:
Foo(int x) : x_(x) { std::cout << "const" << std::endl; }
Foo(const Foo& foo) : x_(foo.x_) { std::cout << "copy const" << std::endl; }
Foo(Foo&& foo) : x_(foo.x_) { std::cout << "move const" << std::endl; }
bool operator< (const Foo& foo) const { return x_ < foo.x_; }
bool operator> (const Foo& foo) const { return x_ > foo.x_; }
void inc() { ++x_; }
int x_;
};
/*
* Doesn't compile. Must return const T& or must accept non-const T&
*
template<typename T>
inline T& my_max(const T& f1, const T& f2)
{
return f1 > f2 ? f1 : f2;
}
*
*/
int main()
{
Foo foo1(6);
Foo foo2(7);
Foo& foo = std::max(foo1, foo2); //Doesn't compile. Must be const Foo&. But then next line fails
foo.inc();
std::cout << foo.x_ << std::endl;
return 0;
}
您这里有 2 个问题:
- 结果中缺少常量限定符
- 返回对常量引用参数的引用很危险
在这种情况下:
Foo& foo = std::max(Foo(6), Foo(7));
编译器将在函数调用之前为参数构造临时对象,并在函数调用后销毁它们 - 因此您最终将引用垃圾。当然,如果您始终使用现有对象,它将起作用 - 但很容易忘记这些限制。
您可以从参数中删除 const,这将解决这两个问题,并且对您来说应该没问题,因为您打算无论如何都要修改对象。
template<typename T>
T my_max(T&& f1, T&& f2) {
return std::forward<T>(f1 > f2 ? f1 : f2);
}
以上比较扎实,会做你需要的。 它确实要求两个参数具有相同的 r/l/const ness,而std::max
则没有。 这就是为什么max
使用const&
.
编写一个更复杂的版本来查找公共引用类别,但它可以以令人惊讶的方式起作用。
因此,不要被上面返回值中缺少&
所愚弄:在您的用例中,上面返回一个引用。 如果传递了右值,则返回一个值。
下面是对super_max
的尝试,如果传递相同类型的左值,则返回一个左值。 如果传递了两种不同的类型或右值,则返回一个副本:
template<class A, class B>
struct max_return:std::common_type<A,B>{};
template<class A>
struct max_return<A&,A&>{
using type=A&;
};
template<class A, class B>
using max_return_t = typename max_return<A,B>::type;
template<class T, class U>
max_return_t<T,U> super_max(T&& t, U&& u) {
if (t < u)
return std::forward<U>(u);
else
return std::forward<T>(t);
}
它也只使用<
,并且更喜欢领带上的左手边。
现场示例
相关文章:
- 从函数返回const char*数组
- 为什么我不能在返回 const 的布尔函数中为类成员变量赋值?C++
- 从内部使用静态 std::string 的函数返回 const char * 是否安全?
- 从类方法返回 "const char*" 作为 std::string&
- 为什么const rvalue合格的std ::可选:: value()返回const rvalue参考
- 通过移动分配从算术运算符过载中返回const值
- 从本机代码返回"const char*"并在java中获取"字符串"
- 为什么我的C 函数拒绝返回const引用
- 通过参考返回和const函数返回const值的函数之间的差异
- 如果我返回const定义的对象,为什么const关键字被取消资格
- 返回const lvalue引用rvalue临时?为什么这项工作
- 内置类型的返回const值
- 返回 const std::string*& from a std::string *tab[11]
- 如何在静态方法中返回const类型
- 返回const引用和非常数成员函数调用
- 为什么不允许我将函数返回 const char* 的结果分配给 char*,bt 可以将字符串文字(常量)分配给 cha
- 在 C++ 中返回 const 字符串引用的字符串文本
- 为什么我们必须从一元前缀运算符重载返回 const 引用
- 在返回 const 错误的函数中传递值
- 为什么我可以将返回 'const T&' 的函数的返回值分配给 'T' 变量,而不是 'T&' 变量?