C++的new有一个选项可以返回空指针,而不是在分配失败时抛出bad_alloc异常.
Foo * pf = new(std::nothrow) Foo(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
(是的,我理解这只会阻止new抛出bad_alloc;它不会阻止Foo的构造函数抛出异常.)
如果你想使用共享指针而不是原始指针,你通常应该使用make_shared,因为它对控制块的分配很聪明.
auto pf = std::make_shared<Foo>(1, 2, 3);
Run Code Online (Sandbox Code Playgroud)
make_shared封装了new,这使得(?)无法选择nothrow版本.因此,您似乎必须放弃make_shared并明确调用new.
std::shared_ptr<Foo> pf(new(std::nothrow) Foo(1, 2, 3));
Run Code Online (Sandbox Code Playgroud)
这消除了使用Foo分配控制块的优化,并且控制块分配可能独立于Foo分配而失败,但我不想关注它.让我们假设控制块很小,所以它的分配在实践中永远不会失败.这是为我担心的Foo分配空间的失败.
有没有办法获得make_shared的单一分配优势,同时保留在为Foo分配空间时简单地获取空指针而不是bad_alloc异常的能力?
对于新操作员,我们具有以下std::nothrow版本:
std::unique_ptr<T> p = new(std::nothrow) T();
Run Code Online (Sandbox Code Playgroud)
我们对于std::make_shared或有这样的东西std::make_unique吗?
有这样的代码:
#include <iostream>
int main(){
for(;;){
int* ptr = new (std::nothrow) int;
if(ptr == 0){
std::cout << 0 << std::endl;
break;
}
}
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但是,这个程序仍然抛出std :: bac_alloc异常,尽管使用std :: nothrow参数调用new.此程序在Visual C++ 2010中编译.为什么抛出异常?
编辑:
在mingw的Windows上使用g ++,一切正常.
“placement new”运算符声明如下:
void* operator new (std::size_t size, void* ptr) noexcept;
Run Code Online (Sandbox Code Playgroud)
但是虽然它不涉及任何实际分配,因此消除了错误的分配异常,但指针仍然可能指向错误的位置,在这种情况下,人们会期望得到范围或上溢/下溢错误,但不会它被声明为noexcept简单地终止执行的事实?
这是否也意味着在 C++11 放置之前 new 将抛出并尝试处理一个std::unexpected,std::set_unexpected而不是直接崩溃?
不应该有大量的放置新“以防万一”吗?
以下代码:
#include <iostream>
#include <iomanip>
#include <string>
#include <utility>
using namespace std;
struct Foo
{
std::string s;
int i;
};
int main()
{
cout << boolalpha << is_nothrow_constructible<Foo>::value << endl;
cout << is_nothrow_constructible<pair<string, int>>::value << endl;
cout << is_nothrow_move_constructible<Foo>::value << endl;
cout << is_nothrow_move_constructible<pair<string, int>>::value << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译时产生以下输出g++ -std=c++11:
true
false
true
true
Run Code Online (Sandbox Code Playgroud)
为什么std::pair<string, int>不是建设性的,Foo而是,为什么它不是可移动的可构造的?
我遇到了一个小的标准头文件<new>。我以前可能没有见过它的直接使用。这是g++ 版本,供感兴趣的人参考。
以下部分是我感兴趣的:
struct nothrow_t { };
extern const nothrow_t nothrow;
/** If you write your own error handler to be called by @c new, it must
* be of this type. */
typedef void (*new_handler)();
/// Takes a replacement handler as the argument, returns the previous handler.
new_handler set_new_handler(new_handler) throw();
Run Code Online (Sandbox Code Playgroud)
struct nothrow_t它及其对象?nothrow该对象真的需要吗extern?new_handler用的?operator new/delete在块中声明extern C++?可以std :: string s; 在任何情况下扔?这是否受标准规范(对C++ 03感兴趣,如果存在差异)?
详题:为什么std:variant的operator=(T&& t)的noexcept规范不依赖于内部类型的析构函数的noexcept规范?
我可以在cppreference上看到
template <class T> variant& operator=(T&& t) noexcept(/* see below */);
Run Code Online (Sandbox Code Playgroud)
是
noexcept(std::is_nothrow_assignable_v<T_j&, T> &&
std::is_nothrow_constructible_v<T_j, T>)
Run Code Online (Sandbox Code Playgroud)
所以这个编译:
struct FooThrow {
~FooThrow() noexcept(false) {throw;}
};
static_assert(std::is_nothrow_assignable_v<std::variant<FooThrow, int>, int>);
Run Code Online (Sandbox Code Playgroud)
但它调用FooThrow的析构函数是noexcept(false):
std::variant<FooThrow, int> x;
x = 3; // throws
Run Code Online (Sandbox Code Playgroud)
这似乎不对.我错过了什么吗?
我试图指定一个函数是nothrow每当析构函数Foo不抛出时.我可以通过使用类型特征来做到这一点std::is_nothrow_destructible<>.我怎么能直接这样做?我已经尝试了以下内容,但如果我取消注释注释行,则无法编译
#include <iostream>
#include <type_traits>
class Foo
{
public:
~Foo() noexcept {}
};
// void f() noexcept(noexcept(~Foo{})) { } // error here
void g() noexcept(std::is_nothrow_destructible<Foo>::value)
{
}
int main()
{
g();
}
Run Code Online (Sandbox Code Playgroud)
我收到一个错误
error: no match for 'operator~' (operand type is 'Foo')
Run Code Online (Sandbox Code Playgroud)
错误说明符noexcept(noexcept(~Foo()))不正常,但对于我可以使用的构造函数noexcept(noexcept(Foo())).我在这里错过了一些明显的语法吗?
c++ ×10
nothrow ×10
exception ×3
c++11 ×2
new-operator ×2
c++03 ×1
constructor ×1
make-shared ×1
std ×1
std-variant ×1
stdstring ×1
variant ×1