如何禁止调用 C++ 中右值对象的 const 成员函数? 2011年?

发布于 2024-11-03 11:10:12 字数 1582 浏览 0 评论 0原文

下面的代码

#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;
}

可能会导致崩溃,因为原始向量已经被破坏了。在 C++ 2011 (c++0x) 中引入右值引用后,如果向量参数是rvalue

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;
}

,因为仍然允许调用右值对象的成员函数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;
}

非常感谢!

The following code

#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;
}

may lead to crash because the original vector is already destructed there. In C++ 2011 (c++0x) after rvalue-reference is introduced in, a deleted function declaration can be used to completely forbid calls to at if the vector argument is an rvalue

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

That looks good, but the following code still cause crash

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

because calls to member function operator [] (size_type) const of an rvalue object is still allowed. Is there any way can I forbid this kind of calls?

FIX:

The examples above is not what I did in real projects. I just wonder if C++ 2011 support any member function qualifying like

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

FIX:

It's great, but I think C++ standard goes too far at this feature. Anyway, I have following code compiled on 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;
}

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

So尛奶瓶 2024-11-10 11:10:12

不,你不应该。我该怎么做 std::cout << at(mkvec(), 0) << std::endl;,这是一个完全合理的事情,如果你禁止我在临时变量上使用 at()

不幸的是,存储对临时变量的引用只是 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

No, and you shouldn't. How am I to do std::cout << at(mkvec(), 0) << std::endl;, a perfectly reasonable thing, if you've banned me from using at() on temporaries?

Storing references to temporaries is just a problem C++ programmers have to deal with, unfortunately.


To answer your new question, yes, you can do this:

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
素罗衫 2024-11-10 11:10:12

只是一个想法:

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

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

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

它将解决像你提到的问题,并且作为奖励将迫使你使用更有效的函数版本:

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

Just an idea:

To disable copying constructor on the vector somehow.

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

Implicit copying of arrays is not that good thing anyway. (wondering why STL authors decided to define such ctor at all)

It will fix problems like you've mentioned and as a bonus will force you to use more effective version of your function:

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文