2

以下代码

#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) 中,如果向量参数是右值,则可以使用已删除的函数声明来完全禁止调用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;
}

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

使固定:

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

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

使固定:

这很棒,但我认为 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;
}

非常感谢!

4

2 回答 2

6

不,你不应该。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
于 2011-04-28T02:27:20.603 回答
-1

只是一个想法:

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

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

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

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

void mkvec(std::vector<std::string>& n)
{
    n.push_back("kagami");
    n.push_back("misao");
}
于 2011-04-28T03:09:41.103 回答