Tim*_*Tim 7 c++ const-reference ref-qualifier
以下代码会导致未定义的行为:
class T
{
public:
const std::string& get() const { return s_; }
private:
std::string s_ { "test" };
}
void breaking()
{
const auto& str = T{}.get();
// do sth with "str" <-- UB
}
Run Code Online (Sandbox Code Playgroud)
(因为const&根据我的理解,生命周期延长不适用于此处)。
为了防止这种情况,一种解决方案可能是添加一个引用限定符get()以防止在 LValues 上调用它:
const std::string& get() const & { return s_; }
Run Code Online (Sandbox Code Playgroud)
但是,由于函数现在既是const又是&合格的,因此仍然可以调用get()RValues,因为它们可以分配给const&:
const auto& t = T{}; // OK
const auto& s1 = t.get(); // OK
const auto& s2 = T{}.get(); // OK <-- BAD
Run Code Online (Sandbox Code Playgroud)
防止这种情况的唯一方法(据我所知)是重载get()一个&&不返回引用的-qualified 变体,或者重载= delete它:
const std::string& get() const & { return s_; }
const std::string& get() const && = delete; // Var. 1
std::string get() const && { return s_; }; // Var. 2
Run Code Online (Sandbox Code Playgroud)
但是,这意味着要实现正确返回(const)引用的 getter 函数,我总是必须提供 Var。1 或 2.,这相当于很多样板代码。
所以我的问题是:是否有更好/更简洁的方法来实现返回引用的 getter 函数,以便编译器可以识别/防止提到的 UB 案例?还是我对问题的理解存在根本性缺陷?
另外,到目前为止,我找不到一个例子,在不处理重载的情况下,添加&到const成员函数会带来任何好处&&……也许任何人都可以提供一个,如果它存在的话?
(我在 MSVC 2019 v142 上使用 C++17,如果这有什么不同的话)
感谢你并致以真诚的问候
目前尚不清楚您正在使用哪些限制。如果这是一个选项,您可以摆脱 getter(s),并让生命周期扩展完成它的工作:
struct T
{
std::string s_ { "test" };
};
const auto& str = T{}.s_; // OK; lifetime extended
Run Code Online (Sandbox Code Playgroud)
对于 getter,您可以选择 1. 提供重复的 getter,或者 2. 接受调用者必须小心,不要假设来自临时 getter 的引用仍然有效。如问题所示。
您可以保留私有访问权限,同时仍然可以通过使用共享所有权轻松进行生命周期管理:
class T
{
std::shared_ptr<std::string> s = std::make_shared<std::string>("test");
public:
// alternatively std::weak_ptr
const std::shared_ptr<const std::string>
get() const {
return s;
}
};
Run Code Online (Sandbox Code Playgroud)
但您必须考虑运行时成本是否值得这么轻松。
| 归档时间: |
|
| 查看次数: |
93 次 |
| 最近记录: |