【问题标题】:Pointer getter to a reference指向引用的指针获取器
【发布时间】:2017-04-01 14:16:17
【问题描述】:

我有一个带有引用的类,并且想要一个返回指针的 getter。

class X {
    std::string& text;
public:
    auto GetText() -> decltype(text) * { return &text); // doesn't work
    X(std::string& text): text(text) {}
};

简单的方法是将指针传递给这个类。但是如果我传递一个引用,我可以得到一个带有 getter 的指针吗?

编辑:这是错误信息

error: cannot declare pointer to 'std::__cxx11::string& {aka class std::__cxx11::basic_string<char>&}'
auto GetText() -> decltype(text) * { return &text);
                                 ^

【问题讨论】:

  • “不起作用”不是一个有用的问题描述。你有编译错误吗?如果是这样,请将它们放在您的问题中。
  • 为什么不直接做std::string* GetText() { return &amp;text; }?您的代码也有拼写错误(当然您的意思是 } 而不是 ) 来关闭该功能)。 `
  • 这一切似乎完全没有必要。
  • 当您从字面上理解“始终自动”的闲置饮水机时会发生这种情况,并且完全没有任何反思地运行它。
  • strip the reference 可以,但为什么要这样做?正如 Kerrek 所说,这一切似乎完全没有必要。

标签: c++ class pointers reference getter


【解决方案1】:

首先,

auto GetText() -> decltype(text) * { return &text); // doesn't work

是声明此签名的一种非常可恶的方式。喜欢

std::string* GetText(){ return &text);

甚至只是

auto GetText(){ return &text);

但这不是代码审查。

这里的问题是你要求一个指向text成员变量的声明类型的指针,它是一个字符串引用(std::string&amp;)。从评论部分,您似乎没有意识到 decltype 尊重其论点的“引用”、“常量”和“易失”。

在 C++ 中不能有指向引用的指针,例如std::string&amp;* 格式错误。致电std::remove_reference_t 应该可以解决该问题,例如

auto GetText() -> std::remove_reference_t<decltype(text)> * { return &text);

但是,在这种情况下,auto 无论如何都会正确推断出您的类型,因此您的显式声明是不必要的。

【讨论】:

  • 令人着迷!谢谢大家。
【解决方案2】:

我为我最初的问题创建了一个test program。该程序有一个带有指针和返回引用的 getter 的类,以及带有引用和返回指针的 getter 的第二个类。

而且似乎-&gt; std::remove_reference_t&lt;decltype(text)&gt; 可以替换为-&gt; decltype(&amp;text)

欢迎评论。

// g++ main.cpp -o test_reference_pointer && strip -s test_reference_pointer && ./test_reference_pointer

#include <iostream>

// A class with a pointer and a getter that returns a reference.
class A {
    std::string *text;
public:
    std::string& GetText_old_way() { return *text; }
    auto GetText_pure_auto() { return *text; }
    auto GetText_pointer_arithmetic() -> decltype(*text) & { return *text; }
public:
    A(std::string *text): text(text) {}
};

// A class with a reference and a getter that returns a pointer.
class B {
    std::string& text;
public:
    std::string *GetText_old_way() { return &text; }
    auto GetText_pure_auto() { return &text; }
    auto GetText_pointer_arithmetic() -> decltype(&text) { return &text; }
    auto GetText_remove_reference() -> std::remove_reference_t<decltype(text)> * { return &text; }
public:
    B(std::string& text): text(text) {}
};

int main() {
    std::string text = "hello, world";

    {//TEST
        A a(&text);
        unsigned int i{0};

        std::cout << "-- Test 1:"<< std::endl;
        ++i; std::cout << i << ". " << a.GetText_old_way() << std::endl;
        ++i; std::cout << i << ". " << a.GetText_pointer_arithmetic() << std::endl;
        ++i; std::cout << i << ". " << a.GetText_pure_auto() << std::endl;
        std::cout << std::endl;
    }

    {//TEST
        B b(text);
        unsigned int i{0};

        std::cout << "-- Test 2:"<< std::endl;
        ++i; std::cout << i << ". " << *b.GetText_old_way() << std::endl;
        ++i; std::cout << i << ". " << *b.GetText_pointer_arithmetic() << std::endl;
        ++i; std::cout << i << ". " << *b.GetText_remove_reference() << std::endl;
        ++i; std::cout << i << ". " << *b.GetText_pure_auto() << std::endl;
        std::cout << std::endl;
    }

    return 0;
}

【讨论】:

  • 注意AGetText_pure_auto 类中的注释正在返回底层字符串的副本而不是引用,这可能不是一个好主意。
  • A类中,在auto GetText_pointer_arithmetic中,decltype(*text)&amp;的尾随&amp;是不必要的; decltype(*text) 是等价的。此外,如果您使用的是 C++14,则此签名可以更紧凑地编写为 decltype(*text) GetText_pointer_arithmetic()decltype(auto)auto&amp;
  • "而且似乎 -> std::remove_reference_t 可以替换为 -> decltype(&text)" 你有点误会了。在这种情况下,std::remove_reference_t&lt;decltype(text)&gt;* 可以替换为 decltype(&amp;text),而不是 std::remove_reference_t&lt;decltype(text)&gt;
  • @ampccartney 为什么auto GetText_pointer_arithmetic() -&gt; decltype(*text) { return *text; }auto GetText_pointer_arithmetic() -&gt; decltype(*text) &amp; { return *text; } 相同?第一个看起来返回一个std::string 而不是std::string&amp;
  • 你明白当你取消引用一个指针时,结果类型是一个引用,对吗?
猜你喜欢
  • 1970-01-01
  • 2012-07-11
  • 2013-01-04
  • 2012-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
相关资源
最近更新 更多