gpt4 book ai didi

c++ - 在异常中不嵌入 std::string 的规则是否仍然适用于移动构造函数?

转载 作者:IT老高 更新时间:2023-10-28 22:59:40 28 4
gpt4 key购买 nike

我前段时间听说我不应该创建具有 std::string 类型字段的异常类。就是这样 Boost website says .基本原理是,如果内存分配失败,std::string 复制构造函数可以抛出异常,如果在捕获当前处理的异常之前抛出异常,则程序终止。

但是,它仍然适用于移动构造函数吗?抛出异常时不会使用移动构造函数而不是复制构造函数吗?我是否正确理解 C++11 不会发生内存分配,不存在异常的机会,并且 std::string 现在在异常类中绝对没问题?

最佳答案

答案是:

是的,您仍然不想将 std::string 嵌入到您的异常类型中。异常(exception)情况经常被复制,有时在您不知情的情况下。例如,在某些平台上,std::rethrow_exception 会复制异常(而在某些平台上则不会)。

为获得最佳实践,请保留您的复制构造函数 noexcept

然而,一切都没有丢失。一个鲜为人知的事实是,C++ 在标准中总是有一个不可变的引用计数字符串类型(带有一个不抛出的复制构造函数),只是带有一个混淆的名称。实际上有两个名字:

logic_error
runtime_error

这些类型的规范要求它们必须包含一个不可变的引用计数的类似字符串的对象。好吧,不是完全不变的。您可以用赋值替换字符串。但是您不能以其他方式修改字符串。

我的建议是从其中一种类型派生,或者如果这 Not Acceptable ,则嵌入其中一种类型并将其视为不可变的引用计数字符串类型:

#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 复制:

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>{}, "");

关于c++ - 在异常中不嵌入 std::string 的规则是否仍然适用于移动构造函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24517528/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com