没有嵌入std :: string的规则在异常仍然保持与移动构造函数? [英] Does rule of not embedding std::string in exceptions still hold with move constructors?

查看:186
本文介绍了没有嵌入std :: string的规则在异常仍然保持与移动构造函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我听说过一段时间以前,我不应该创建具有 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆