我们正在尝试在C++ 17下测试一些代码并将其更改为std::uncaught_exception.我似乎无法让GCC提供以下价值__cplusplus:
$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$
Run Code Online (Sandbox Code Playgroud)
和:
$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
Run Code Online (Sandbox Code Playgroud)
__cplusplus使用C++ 17时有什么价值?
我最近开始将大量现有的C++应用程序代码移植到C++ 11,现在我转换为新的智能指针std :: unique_ptr和std :: shared_ptr,我有一个关于自定义删除的具体问题.我想添加一个lambda记录器来查看我的删除被调用的位置但是我无法获得要编译的数组特化版本.建议将非常感谢.
我已经白白被搜索用于阵列专业化一个定制删除的一个例子的unique_ptr为VC++ 10或GCC 4.5.2+.我想在lambda中调用删除器时打印一条日志消息 - 主要是为了确保我认为超出范围的所有指针都这样做.这可能是专业化的阵列版本吗?我可以使用非数组版本,如果我将外部结构"MyArrayDeleter"作为第二个参数传递,我也可以使用数组特化.还有一件事,是否有可能删除丑陋的std :: function,因为我认为我可以让lambda签名数字出来.
struct MySimpleDeleter {
void operator()(int* ptr) const {
printf("Deleting int pointer!\n");
delete ptr;
}
};
struct MyArrayDeleter {
void operator()(int* ptr) const {
printf("Deleting Array[]!\n");
delete [] ptr;
}
};
{
// example 1 - calls MySimpleDeleter where delete simple pointer is called
std::unique_ptr<int, MySimpleDeleter> ptr1(new int(5));
// example 2 - correctly calls MyArrayDeleter where …Run Code Online (Sandbox Code Playgroud) 我在Github上发现了一个里面有一个很奇怪的单行代码的函数:
std::unique_ptr<std::remove_pointer<HANDLE>::type, void(*)(HANDLE)> hDevice{h, [](HANDLE handle){CloseHandle(handle);}};
Run Code Online (Sandbox Code Playgroud)
作为一个从不处理c ++的人,我不知道它会做什么。
我想,这是两个嵌套的匿名函数,它们以某种方式与std::remove_pointerand std::unique_ptr调用连接。我CloseHandle在内部函数中看到一个WinAPI 调用,并假设我应该从中开始分析。我不能说更多。
可能是两个嵌套的泛型。
花括号和“大于”符号的使用对我来说也很奇怪。它打破了我所知道的所有规范案例。
请帮助了解这个集团。我不知道如何谷歌其部分。
库定义了不透明的数据类型:
\n\nstruct OpaqueStruct;\nRun Code Online (Sandbox Code Playgroud)\n\n并且客户端代码必须获取并释放OpaqueStruct*. 我可以访问库源。
不幸的是,既不能存储该指针shared_ptr,也unique_ptr不能存储该指针,从而出现错误: invalid application of \xe2\x80\x98sizeof\xe2\x80\x99 to incomplete type。
我能想到的最好的办法就是从这篇文章中借用finally守卫 。
\n\n如何将 RAII 用于不透明结构指针?
\n我目前正在尝试调用sqlite3库函数,它希望我传递它sqlite3**.
这是我目前的代码.我有一个工作部分,一部分给我一个错误:
sqlite3 *sqlite = m_db.get();
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &sqlite))
{
}
if (sqlite3_open(std::string(m_dbName.begin(), m_dbName.end()).c_str(), &(m_db.get()) ))
{
}
Run Code Online (Sandbox Code Playgroud)
我的m_db字段看起来像这样:
std::unique_ptr<sqlite3> m_db = nullptr;
Run Code Online (Sandbox Code Playgroud)
在我展示的两个例子中,第一个是完美的.但是,第二个给了我这个错误.请注意,这是来自&(m_db.get())部分:
“Address expression must be an lvalue or a function designator”
Run Code Online (Sandbox Code Playgroud)
我读了一些关于左值和右值的内容,但我似乎无法弄清楚为什么这种语法是不可能的.据我所知,现在问题是.get()操作的返回值仅仅是一个临时表达式结果,因此在内存中没有可识别的位置,我可以从中获取地址.
我想,必须有一种方法可以在一个声明中实现这一点.
任何人都可以向我解释为什么这不起作用,我怎么可能解决它?
我目前正在使用一个C库,该库定义了许多数据类型,所有这些数据类型都需要由用户管理其生命周期。以这种方式定义了许多功能:
int* create() {
return new int();
}
void destroy(int* i) {
delete i;
}
Run Code Online (Sandbox Code Playgroud)
创建后不需要访问其中的大多数。它们只需要存在。因此,我正在尝试使用unique_ptr声明的来管理它们,在我需要它们生存的范围内。
这样的声明看起来像这样:
// Note that I'm avoiding writing the type's name manually.
auto a = std::unique_ptr<std::decay_t<decltype(*create())>, decltype(&destroy)>{create(), &destroy};
Run Code Online (Sandbox Code Playgroud)
但这过于冗长,因此我将其封装在实用程序功能模板中:
template<typename T>
auto make_unique_ptr(T* p, void (*f)(T*)) {
return std::unique_ptr<T, decltype(f)>(p, f);
}
Run Code Online (Sandbox Code Playgroud)
使用这种方式:
auto b = make_unique_ptr(create(), &destroy);
Run Code Online (Sandbox Code Playgroud)
这看起来不错,但是引入了一个非标准函数,该函数除了作为某些声明的语法糖外没有其他实际用途。我的同事甚至可能都不知道它的存在,最终以不同的名称创建了它的其他版本。
c ++ 17引入了类模板参数推导。我认为这是解决我的问题的完美解决方案:一种无需使用用户定义的包装器即可推论所有这些类型的标准方法。所以我尝试了这个:
auto c = std::unique_ptr{create(), &destroy};
Run Code Online (Sandbox Code Playgroud)
按照C ++编译器和模板的规则,此操作将失败,并显示几行长的错误消息。以下是相关部分:
int* create() {
return new int();
}
void destroy(int* i) { …Run Code Online (Sandbox Code Playgroud) std::default_delete 可以专门化以允许std::unique_ptrs轻松管理必须通过调用某些自定义销毁函数而不是使用 来销毁的类型delete p;。
基本上有两种方法可以确保对象由std::shared_ptrC++ 中的 a 管理:
std::make_shared使用或创建由共享指针管理的它std::allocate_shared。这是首选方式,因为它将所需的两个内存块(有效负载和引用计数)合并为一个。尽管仅std::weak_ptr剩下 s,但对引用计数的需求仍然必然会限制有效负载的内存。
第二种情况,当不提供自定义删除器时很有趣:
\n\n具体来说,它被定义为使用自己的未指定类型的删除器,该删除器分别使用delete [] p;或delete p;,具体取决于std::shared_ptr是否为数组实例化。
引自 n4659 (~C++17):
\n\n\nRun Code Online (Sandbox Code Playgroud)\n\ntemplate<class Y> explicit shared_ptr(Y* p);\n4 要求:
Y必须是完整的类型。表达式delete[] p,whenT是数组类型,或delete p,whenT不是数组类型,应具有良好定义的行为,并且不应引发异常。
\n 5 E\xef\xac\x80ects:当T不是 Array 类型时,构造一个shared_ptr …
我的代码
void build(std::vector<RKD <DivisionSpace> >& roots, ...) {
try {
// using a local lock_guard to lock mtx guarantees unlocking on destruction / exception:
std::lock_guard<std::mutex> lck (mtx);
roots.push_back(RKD<DivisionSpace>(...));
}
catch (const std::bad_alloc&) {
std::cout << "[exception caught when constructing tree]\n";
return;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,实际工作应该连续进行,而不是并行进行.
构造函数RKD可以与其他构造函数并行运行RKD.然而,推回物体std::Vector是一个关键部分,对吗?
我要构建的对象的数量是已知的.在实践中它将在[2,16]范围内.理论上它可以是任何正数.
此外,我对它们将被插入容器的顺序并不感兴趣.
所以我可以这样做:
RKD tree = RKD(...);
mutex_lock(...);
roots.push_back(tree);
Run Code Online (Sandbox Code Playgroud)
然而,这意味着复制,不是吗?
我应该怎么做才能使我的代码并行?
由于这个答案,我决定使用锁(而不仅仅是互斥锁).
我正在尝试使用mupdf创建一个程序(在Qt中),这将允许我将文档的对象列为列表,并允许我选择要呈现/不呈现的对象.由于Qt是c ++,而且我对它更熟悉,我试图在m ++中用C++类包装结构.
现在我的问题是这个 - 你在mupdf中做的第一件事就是创建一个全局上下文,它传递给所有东西,包括清理和删除结构的函数.
我熟悉创建一个有重载的对象,operator()很像:
struct ContextDeleter
{
inline void operator()(fz_context* ctx)
{
fz_drop_context(ctx);
}
};
Run Code Online (Sandbox Code Playgroud)
然后我可以交给unique_ptr-
std::unique_ptr<fz_context, ContextDeleter> ctxPtr;
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚的是如何用以下函数做同样的事情:
fz_drop_page(ctx, page);
Run Code Online (Sandbox Code Playgroud)
即:
struct PageDeleter
{
inline void operator()(fz_context* ctx, fz_page* pg)
{
fz_drop_page(ctx, pg);
}
}
Run Code Online (Sandbox Code Playgroud)
这显然是不正确的,但我正在努力实现.
如何为unique_ptr包含2个参数(在这种情况下是必要的上下文指针)创建一个删除器?有没有办法让我unique_ptr知道删除页面的上下文指针(在本例中)?或者(我曾经想过)我需要创建一些包装的东西,unique_ptr所以我可以把它上传给上下文以便稍后删除(还没有完全考虑过).
我在这里看到了这些例子:
如何将自定义删除器与std :: unique_ptr成员一起使用?
和
但我无法弄清楚如何使它们在我的情况下工作.
编写下面代码的正确方法是什么?
我有一个内存管理器,它提供了我char *的,但我需要使用数组uint32_t.我如何解决严格的别名规则?我理解,对于单个对象,建议只复制内容,memcpy()但对于一组对象,该解决方案是不可接受的.
char* ptr = manager()->Allocate(1000 * sizeof(uint32_));
uint32_t* u32ptr = reinterpret_cast<uint32_t*>(ptr);
....
u32ptr[x] = y;
Run Code Online (Sandbox Code Playgroud) c++ pointers dynamic-memory-allocation reinterpret-cast c++11