以下代码
#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;
}
非常感谢!
答案 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");
}