没有嵌入std :: string的规则在异常仍然保持与移动构造函数? [英] Does rule of not embedding std::string in exceptions still hold with move constructors?
问题描述
我听说过一段时间以前,我不应该创建具有 std :: string
类型的异常类。这就是 Boost网站说的。原理是如果内存分配失败, std :: string
复制构造函数可以抛出异常,如果在捕获当前处理的异常之前抛出异常,程序终止。
I heard some time ago that I should not create exception classes which would have fields of std::string
type. That's what Boost website says. The rationale is that std::string
copy constructor can throw an exception if memory allocation fails, and if an exception is thrown before the currently processed exception is caught, the program is terminated.
但是,它仍然保持在移动构造函数的世界?在抛出异常时,不会使用move构造函数而不是复制构造函数?我理解正确的C ++ 11没有发生内存分配,没有异常的机会, std :: string
在绝对罚款在异常类现在吗? p>
However, does it still hold in the world of move constructors? Won't the move constructor be used instead of the copy constructor when throwing an exception? Do I understand correctly that with C++11 no memory allocation will take place, no chance of exception exists and std::string
is absolutely fine in exception classes now?
推荐答案
答案是:
是的,你还是不想以将 std :: string
嵌入到您的异常类型中。异常通常被复制,有时没有你的知识。例如,在一些平台上 std :: rethrow_exception
将复制异常(在某些平台上不会)。
Yes, you still don't want to embed a std::string
into your exception types. Exceptions are often copied, sometimes without your knowledge. For example, on some platforms std::rethrow_exception
will copy the exception (and on some it won't).
为了最佳实践,保持您的副本构造函数 noexcept
。
For best practice, keep your copy constructor noexcept
.
但是并不会丢失。一个有点已知的事实是,C ++总是在标准中有一个不可变的ref计数字符串类型(带有非throwing的拷贝构造函数),只是一个混淆的名字。实际上有两个名称:
However all is not lost. A little known fact is that C++ has always had within the standard an immutable ref-counted string type (with a non-throwing copy constructor), just with an obfuscated name. Two names actually:
logic_error
runtime_error
这些类型的规范是这样的,它们必须包含一个不可变的ref计数的字符串对象。嗯,不是完全不变的。您可以使用赋值替换字符串。但是你不能修改字符串。
The specs for these types are such that they must contain an immutable ref-counted string-like object. Well, not completely immutable. You can replace the string with an assignment. But you can't otherwise modify the string in place.
我的建议是从这些类型之一派生,或者如果这是不可接受的,嵌入其中一个类型并将其视为不可变ref计数字符串类型:
My advice is to either derive from one of these types, or if that is not acceptable, embed one of these types and treat it as an immutable ref-counted string type:
#include <stdexcept>
#include <iostream>
class error1
: public std::runtime_error
{
using msg_ = std::runtime_error;
public:
explicit error1(std::string const& msg)
: msg_(msg)
{}
};
class error2
{
std::runtime_error msg_;
public:
explicit error2(std::string const& msg)
: msg_(msg)
{}
char const* what() const noexcept {return msg_.what();}
};
void
test_error1()
{
try
{
throw error1("test1");
}
catch (error1 const& e)
{
std::cout << e.what() << '\n';
}
}
void
test_error2()
{
try
{
throw error2("test2");
}
catch (error2 const& e)
{
std::cout << e.what() << '\n';
}
}
int
main()
{
test_error1();
test_error2();
}
std :: lib将处理所有的字符串处理和内存管理,您可以在交易中获得 noexcept
复制:
The std::lib will take care of all the string-handling and memory management for you, and you get noexcept
copying in the bargain:
static_assert(std::is_nothrow_copy_constructible<error1>{}, "");
static_assert(std::is_nothrow_copy_assignable <error1>{}, "");
static_assert(std::is_nothrow_copy_constructible<error2>{}, "");
static_assert(std::is_nothrow_copy_assignable <error2>{}, "");
这篇关于没有嵌入std :: string的规则在异常仍然保持与移动构造函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!