Cli*_*ton 1 c++ expression-templates c++11
使用以下代码时,不显示"hello2",因为在第3行上创建的临时字符串在执行第4行之前死亡.在第1行使用#define避免了这个问题,但有没有办法在不使用#define的情况下避免这个问题?(C++ 11代码没问题)
#include <iostream>
#include <string>
class C
{
public:
C(const std::string& p_s) : s(p_s) {}
const std::string& s;
};
int main()
{
#define x1 C(std::string("hello1")) // Line 1
std::cout << x1.s << std::endl; // Line 2
const C& x2 = C(std::string("hello2")); // Line 3
std::cout << x2.s << std::endl; // Line 4
}
Run Code Online (Sandbox Code Playgroud)
澄清:
请注意,我相信Boost uBLAS存储引用,这就是为什么我不想存储副本.如果您建议我按值存储,请解释为什么Boost uBLAS出错并且按值存储不会影响性能.
通过引用存储的表达式模板通常是为了提高性能,但需要注意的是它们只能用作临时表
取自Boost.Proto 的文档(可用于创建表达式模板):
注意精明的读者会注意到上面定义的对象y将保留对临时int的悬空引用.在Proto解决的各种高性能应用程序中,通常在任何临时对象超出范围之前构建和评估表达式树,因此这种悬空参考情况通常不会出现,但它肯定是需要注意的事情. .Proto提供了深层复制表达式树的实用程序,因此它们可以作为值类型传递,而不用担心悬空引用.
在您的初始示例中,这意味着您应该:
std::cout << C(std::string("hello2")).s << std::endl;
Run Code Online (Sandbox Code Playgroud)
这样C临时永远不会超过std::string临时.或者,您可以s像其他人指出的那样成为非参考成员.
既然你提到了C++ 11,将来我希望表达式树按值存储,使用移动语义来避免昂贵的复制和包装,如std :: reference_wrapper,仍然可以通过引用存储.这样可以很好地发挥作用auto.
您的代码可能是C++ 11版本:
class C
{
public:
explicit
C(std::string const& s_): s { s_ } {}
explicit
C(std::string&& s_): s { std::move(s_) } {}
std::string const&
get() const& // notice lvalue *this
{ return s; }
std::string
get() && // notice rvalue *this
{ return std::move(s); }
private:
std::string s; // not const to enable moving
};
Run Code Online (Sandbox Code Playgroud)
这意味着代码C("hello").get()只会分配一次内存,但仍然可以很好地使用
std::string clvalue("hello");
auto c = C(clvalue);
std::cout << c.get() << '\n'; // no problem here
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
380 次 |
| 最近记录: |