【问题标题】:const-reference qualified member functionconst-reference 限定成员函数
【发布时间】:2015-11-26 14:24:25
【问题描述】:

引用限定成员函数的股票示例似乎是这样的:

#include <stdio.h>
#include <stdexcept>
#include <string>

// Easy access to literals
using namespace std::literals;

// File wrapper
class File {
  private:
    //  The wrapped file
    FILE *_file;
  public:
    File(const char *name) : 
        _file(fopen(name, "r")) { 
        // unable to open the file?
        if (!_file) throw std::runtime_error{ "Unable to open file: "s + name };
    } 
    ~File() { 
        fclose(_file);
    } 

    //  Convert to the underlying wrapped file
    operator FILE *() & { 
        return _file;
    } 

    // TODO: Member functions for working with the file
};

这很好用。无法直接从未命名的临时文件中检索底层 FILE 指针。但是,如果我们使强制转换运算符也具有 const 限定,这似乎不再有效。

即使这是一个非常有用的想法,不同的编译器也会毫无怨言地接受它。以 std::string::c_str() 成员函数为例。你觉得它应该是引用限定的(因为否则你有一个无效的指针)但它不是。

这是 C++11 标准中的一个漏洞吗?我在这里遗漏了什么吗?

【问题讨论】:

  • 你不能让代码更密集一点吗?它不仅仅是 2 种方法的页面
  • c_str() 在参数中很有用,即使它是临时的。在f(g().c_str()); 中,有限的生命周期是可以的。
  • 旁白:并非所有的右值引用都是临时的。

标签: c++ c++11


【解决方案1】:

临时对象可以绑定到const&amp; 限定对象,并且 ref 限定符有效地限定隐式传递的对象 (*this)。如果您想阻止对临时对象的调用但允许左值,您可以= delete 右值引用重载并实现左值版本。对两个运算符使用 const 限定的引用限定符只需要一个实现和一个 = deleted 实现:

class File {
    // ...
    FILE* _file;
public:
    operator FILE*() const&& = delete;
    operator FILE*() const& { return this->_file; }
    // ...
};

最终的结果是,您只能将转换用于您转到左值的对象:

int main() {
    File       f;
    File const cf{};

    FILE* fp = f;              // OK
    FILE* cfp = cf;            // OK
    FILE* tfp = File();        // ERROR: conversion is deleted
    FILE* mfp = std::move(cf); // ERROR: conversion is deleted  
}

【讨论】:

  • 这似乎是解决方案。我认为没有必要包含非常量运算符函数。没有它,我似乎不会有任何不良行为。
  • 你可以使用const&amp;&amp; = delete,而不是&amp;&amp; = delete,否则const rvalue会绑定到const&amp;重载
  • @PiotrSkotnicki:谢谢 - 我不知道这个漏洞。我已经相应地更新了答案。
猜你喜欢
  • 2020-03-24
  • 1970-01-01
  • 2011-06-04
  • 2014-05-25
  • 2016-08-17
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2023-03-14
相关资源
最近更新 更多