2016-07-05 41 views
-2

这里const auto &&真的没用吗?

https://youtu.be/dTeKf5Oek2c?t=2939

斯蒂芬吨Lavavej说,在一次谈话说const auto &&是没有用的。

是不是下面的有效用例?

NonMovableNonCopyable create() { 
    // ... 
    return {}; 
} 

const auto && obj = create(); 

混凝土应用程序:在XLL代码,MS Excel中一般不喜欢它xloper s到被复制或移动将其返回,因为在复制或移动它将不能正确地释放它们之后。

+3

你可以用'const auto&'完成同样的事情。 – StoryTeller

+2

仅供参考,您可以在所需的时间点击YouTube视频,然后选择“当前时间复制视频网址”,该链接可直接链接到该时间点:https://youtu.be/dTeKf5Oek2c?t = 2937 – Tas

+3

您应该或许可以解释为什么'const auto &&'在问题的主体中被认为没有用处。 – juanchopanza

回答

1

Const T &&是非常有用的,如果T有一个可变字段。一个常见的例子是bool m_movedFrom,它被初始化为false,并在被移出时被设置为true。这允许你的对象的其余部分 - 例如资源句柄保持为const。

class Resource // use this as a base class of const correct classes 
{ 
private: 
    mutable bool m_movedFrom; 

protected: 
    Resource() 
    : m_movedFrom(false) 
    { 
    } 

    Resource(const Resource&& other) 
    : m_movedFrom(false) 
    { 
     other.m_movedFrom = true; 
    } 

    bool isOwning() const // call from descendant's destructor 
    { 
     return m_movedFrom; 
    } 
}; 

编辑:一个更复杂的例子当对象本身是常量,而是一个全球性的状态不是解释(不是说这是解决这个的好方法,它是只说明目的):

#include <iostream> 
#include <string> 
#include <vector> 
#include <algorithm> 

typedef std::string object_type; 
typedef std::string seek_type; 

class GoalSeeker 
{ 
private: 
    static std::vector<const GoalSeeker*> s_store; 

    const std::vector<const GoalSeeker*>::iterator m_iter; 
    const object_type        m_data; 

public: 
    GoalSeeker(const object_type& data) 
    : m_iter(s_store.insert(s_store.end(), this)), m_data(data) 
    { 
    } 

    GoalSeeker(const GoalSeeker&) = delete; 

    GoalSeeker(const GoalSeeker&& other) 
    : m_iter(other.m_iter), m_data(other.m_data) 
    { 
     *m_iter = this; 
    } 

    ~GoalSeeker() 
    { 
     if(*m_iter == this) 
     { 
      // cleanup m_data 
     } 
    } 

    static bool seek(const seek_type& needle) 
    { 
     return std::find_if(s_store.begin(), s_store.end(), 
      [&needle](const GoalSeeker* haystack) 
      { 
       return haystack->m_data.find(needle) != std::string::npos; 
      }) != s_store.end(); 
    } 
}; 

std::vector<const GoalSeeker*> GoalSeeker::s_store = {}; 

GoalSeeker fn() 
{ 
    return GoalSeeker("def"); 
} 

int main() { 
    GoalSeeker a("abc"     ); 
    GoalSeeker b("cde"     ); 
    GoalSeeker s((const GoalSeeker&&) fn()); 

    std::cout << GoalSeeker::seek("de") << " " << GoalSeeker::seek("fff"); 
} 
+1

不知道我在这里理解你的意思。我对我来说不太合适。你能提供一个具体的例子吗? –

+0

编辑提供一个例子。 – lorro

+0

好的,在你使用的代码中有C++ 11函数返回'const T'。这是*不是一个好主意*。猜测它是由Scott Meyers读过旧的C++ 11之前的东西,曾经主张C++ 03。在考虑可能的情况时,它并没有出现在我的脑海里,这是非常罕见的。所以,const &&并不完全合理。 –

0

而不是

const auto && obj = create(); 

...写信只是

const auto object = create(); 

...或

const auto object{ create() }; 

=依赖于编译器eliding拷贝构造函数调用,但我不知道任何现存的编译器,它无法做到这一点。

获得的清晰度比国际海事组织提供的担保要重要得多(如果使用参考,请使用普通&参考)。也就是说,避免让维护程序员浪费时间来理解参考的基本原理。如果明确指定了类型,那么可能是多态引用的情况,Petru Marginean的诡计,但是auto这是不可能的,因此维护程序员在一段时间的付费时间内仍然摸不着头。


在另一方面,const T&&可以是函数重载作为参数类型有用搭上临时作为参数的情况下,以同样的方式作为&&限定符成员函数被认为具有足够有用将要通过在标准中。例如,即使我不建议这样做,如果存储了一个指向实际参数的指针供以后使用,那么可能不希望存储指向临时指针的指针,该临时指针最终会成为悬挂指针:

struct Expr{ virtual ~Expr(){} }; 

struct Sum_expr: Expr 
{ 
    const Expr*  a_; 
    const Expr*  b_; 

    Sum_expr(Expr const& a,Expr const& b): a_(&a), b_(&b) {} 

    template< class A > 
    Sum_expr(A&&, Expr const&& b) = delete; 

    template< class B > 
    Sum_expr(Expr const&& a, B&&) = delete; 
}; 

auto main() 
    -> int 
{ 
    Expr a; 
    Expr b; 
    Sum_expr sum{ a, b }; 
    Sum_expr sum2{ a, Expr() };  //! Nope, won't compile. 
} 

注:这里A&&B&&同时支持右值和左值实际参数,即他们不一定右值引用,因为他们普遍引用

但是,不是重载和区分的情况下,我认为我会使一个指针正式参数,即使一个指针技术上可以是一个空指针,因为就我所见,它与我习以为常的更清楚地传达意图。

Sum_expr(Expr const* a, Expr const* b);