我怎样才能禁止在C ++ 2011中调用rvalue对象的const成员函数?

时间:2011-04-28 01:33:59

标签: c++ c++11 rvalue deleted-functions

以下代码

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

std::string const& at(std::vector<std::string> const& n, int i)
{
    return n[i];
}

std::vector<std::string> mkvec()
{
    std::vector<std::string> n;
    n.push_back("kagami");
    n.push_back("misao");
    return n;
}

int main()
{
    std::string const& s = at(mkvec(), 0);
    std::cout << s << std::endl; // D'oh!
    return 0;
}

可能导致崩溃,因为原始矢量已在那里被破坏。在引入了rvalue-reference之后的C ++ 2011(c ++ 0x)中,如果vector参数是rvalue,则可以使用 deleted function 声明来完全禁止对at的调用

std::string const& at(std::vector<std::string>&&, int) = delete;

看起来不错,但以下代码仍会导致崩溃

int main()
{
    std::string const& s = mkvec()[0];
    std::cout << s << std::endl; // D'oh!
    return 0;
}

因为仍然允许调用rvalue对象的成员函数operator [] (size_type) const。有什么办法可以禁止这种电话吗?

FIX:

上面的例子不是我在实际项目中所做的。我只是想知道C ++ 2011是否支持任何符合

的成员函数
class A {
    void func() rvalue; // Then a call on an rvalue object goes to this overload
    void func() const;
};

FIX:

这很棒,但我认为C ++标准在这个功能上走得太远了。无论如何,我在clang ++ 2.9上编译了以下代码

#include <cstdio>

struct A {
    A() {}

    void func() &
    {
        puts("a");
    }

    void func() &&
    {
        puts("b");
    }

    void func() const &
    {
        puts("c");
    }
};

int main()
{
    A().func();
    A a;
    a.func();
    A const b;
    b.func();
    return 0;
}

非常感谢!

2 个答案:

答案 0 :(得分:6)

不,你不应该。如果你禁止我在临时使用std::cout << at(mkvec(), 0) << std::endl;,我该如何做at(),这是一个非常合理的事情?

不幸的是,存储对temporaries的引用只是C ++程序员必须处理的一个问题。


要回答您的新问题,是的,您可以这样做:

class A {
    void func() &; // lvalues go to this one
    void func() &&; // rvalues go to this one
};

A a;
a.func(); // first overload

A().func(); // second overload

答案 1 :(得分:-1)

只是一个想法:

以某种方式禁用向量上的复制构造函数。

vector ( const vector<T,Allocator>& x );

无论如何,隐式复制数组并不是件好事。 (想知道为什么STL作者决定完全定义这样的ctor)

它会修复你提到过的问题,并且会奖励你使用更有效的功能版本:

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}