- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有这门课:
template<typename T, size_t N>
class Array {
private:
T array[N];
public:
template <typename... InitValues>
constexpr Array(InitValues... init_values)
: array{ init_values... } {}
[[nodiscard]]
consteval int len() const noexcept { return sizeof(array) / sizeof(T); }
}
我想知道,对于这样一个简单的成员函数,我应该什么时候提供必要的ref-qualified
过载。
使用实际代码,我可以编译并运行以下代码:
constexpr collections::Array a = collections::Array<long, 5>{1L, 2L, 3L};
SECTION("length of the array") {
REQUIRE( a.len() == 5 );
REQUIRE( collections::Array<int, 1>{1}.len() == 1 );
}
1- 为什么我可以编译第二个 REQUIRE
包含带有 rvalue
的调用?
现在我要更改 len()
对此的成员函数:
[[nodiscard]]
consteval int len() const& noexcept { return sizeof(array) / sizeof(T); }
2- 为什么我可以用 const&
编译两者?我想它们是两种不同的 ref-qualified 用法。我假设我可以用第一个电话调用电话,即 lvalue
, 但不明白为什么我可以编译第二个定义了 len()
方法为 const&
.
上次更改:
[[nodiscard]]
consteval int len() const&& noexcept { return sizeof(array) / sizeof(T); }
最后,我在 a.get<I>()
上遇到编译器错误.
'this' argument to member function 'len' is an lvalue, but function has rvalue ref-qualifier
REQUIRE( a.len() == 5 );
如果我注释掉那行代码然后运行就完美了:
REQUIRE( collections::Array<int, 1>{1}.len() == 1 );
而且我还可以使用 std::move(a)
执行a
的类型转换到rvalue reference
并编译代码。但我不想那样做。
ref-qualified
对这些示例进行编码的正确方法是什么?重载?编辑:
我将添加另一个成员函数,它可能会根据 ref-qualified 实现(或者我认为可能发生的情况)做不同的事情:
template <size_t I>
requires concepts::AccessInBounds<I, N>
constexpr T get() const noexcept {
return array[I];
}
template <size_t I>
requires concepts::AccessInBounds<I, N>
constexpr T& get() const& noexcept {
return array[I];
}
最佳答案
对于问题 1:为什么不呢?规则与左值相同:无论对象的常量性如何,都可以调用 const 成员函数。
对于问题 2:因为它意味着与具有 const& 函数参数相同:可以使用任何左值或右值调用该函数。它的存在主要是为了让您区分左值和右值重载:
class Array {
// These two declarations would be ambiguous for Array rvalues
// int len() const;
// int len() &&;
// These are not: your test expressions will use different overloads
int len() const&;
int len() &&;
};
您编辑中的两个函数对于左值和右值也是不明确的。一个激励性的例子更像是这样:假设我的类为某些资源提供功能,这些资源复制起来可能很昂贵,但移动起来更便宜,比如 std::vector。
template<class T>
class VectorView {
std::vector<T> vector;
public:
// ...
constexpr std::vector<T> const& base() const noexcept { return vector; }
};
现在,此类的用户无法将 vector 数据的所有权从 View 对象传回,即使这在对右值调用 base() 函数时很有用。因为避免为您不需要的东西付费符合 C++ 的精神,您可以通过添加一个右值限定的重载来实现这一点,该重载使用 std::move 返回一个右值引用。
因此,是否需要这种重载的答案视情况而定,不幸的是,这也符合 C++ 的精神。如果您正在为标准库实现类似于我的示例类的东西,那么您当然会这样做,因为它基于 std::ranges::owning_view。 .正如您在该页面上看到的那样,它涵盖了所有四种可能的 base()。如果您只是使用对源范围的引用,那么从该对象移动将是意外且不合适的,因此相关的 ref_view只有一个像我写的那样的 const base() 函数。
编辑 至于移动语义,数组和 vector 之间的区别在于 Array<T,N>
基于T[N]
, 而 std::vector<T>
基于T*
.移动数组需要N次移动操作(线性时间复杂度),移动是否是对拷贝的改进取决于T。另外,它需要2N个元素的内存空间。另一方面,一个 vector 只需要三个指针来完成它的工作,所以它可以在常数时间内移动,而复制仍然需要线性时间。
简而言之,这种潜在的 yield 是移动语义和右值引用的基本原理。还具有 && 限定成员函数的能力完善了此语言功能,但不如移动构造函数和赋值函数重要。我还找到了 this question 的答案很有用,因为它们提供了更多引用限定重载的示例。
关于c++ - 为成员函数生成必要的引用限定重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74760736/
我正在使用 this solution在二进制矩阵中找到与图像边界对齐的矩形。假设现在我想找到一个不与图像边框对齐的矩形,并且我不知道它的方向;找到它的最快方法是什么? 为了示例,让我们寻找一个仅包含
else: 行在这个 Python 程序中是否正确/必要? from random import randrange for n in range(10): r = randrange(0,1
在 TDPL 7.1.5.1 中讨论了将 Widget w2 分配给 w1 并且作者指出“将 w2 逐个字段分配给 w1 会将 w2.array 分配给 w1.array——一个简单的数组边界分配,而
我是一名优秀的程序员,十分优秀!