以下短节目
#include <vector>
#include <iostream>
std::vector<int> someNums()
{
return {3, 5, 7, 11};
}
class Woop
{
public:
Woop(const std::vector<int>& nums) : numbers(nums) {}
void report()
{
for (int i : numbers)
std::cout << i << ' ';
std::cout << '\n';
}
private:
const std::vector<int>& numbers;
};
int main()
{
Woop woop(someNums());
woop.report();
}
Run Code Online (Sandbox Code Playgroud)
有一个悬空引用问题,似乎没有编译器警告过。问题是临时文件可以绑定到 const-refs,然后您可以保留它。那么问题是;有没有办法避免陷入这个问题?最好是不涉及牺牲常量正确性或总是制作大对象的副本。
C++11§23.2.1.10规定:
除非另有说明,否则本条款中定义的所有容器类型均满足以下附加要求:
- 如果插入单个元素时insert()或emplace()函数抛出异常,则该函数不起作用.
- 没有erase(),clear(),pop_back()或pop_front()函数抛出异常.
关于第一个要点,容器如何保证?构造函数T
可能有副作用.它不应该" 对容器没有影响 "
关于第二个要点,这通常称为allocator::deallocate(T*,size_t)
不是noexcept
.为什么最终的异常会被掩盖?
我希望clang格式如下:
switch (x)
{
case long_name: return 1;
case sn: return 2;
}
Run Code Online (Sandbox Code Playgroud)
该AllowShortCaseLabelsOnASingleLine
选项将它们放在同一行,
但我还没有找到一种方法来使语句对齐.
使用shared_ptr,您可以使用自定义删除器,例如:
auto fp = shared_ptr<FILE>( fopen("file.txt", "rt"), &fclose );
fprintf( fp.get(), "hello\n" );
Run Code Online (Sandbox Code Playgroud)
fclose
无论函数如何退出,这都将记住该文件.
但是,重新计算局部变量似乎有点过分,所以我想使用unique_ptr
:
auto fp = unique_ptr<FILE>( fopen("file.txt", "rt"), &fclose );
Run Code Online (Sandbox Code Playgroud)
但是,这不会编译.
这是一个缺陷吗?有一个简单的解决方法吗?我错过了一些微不足道的东西?
标准库中的各种容器按值来获取谓词.
例如:
从§23.3.5开始 std::list
template <class Predicate>
void remove_if(Predicate pred);
Run Code Online (Sandbox Code Playgroud)
将谓词作为转发引用是否有优势?
它可能不是那么常见,但可能是仿函数很难复制.
一般的推荐是按值来判断谓词,在这种情况下为什么?
std::size_t
在以下任何一个中定义:
<cstddef>
<cstdio>
<cstdlib>
<cstring>
<ctime>
<cwchar>
刚才被认为是"犹太人" std::size_t
?
以下代码段在clang和MSVS中编译,但不在gcc中编译.
template<typename T> class clone_ptr;
template<typename T, typename U, typename ...Args>
clone_ptr<T> make_cloned( Args ...args );
// note: everything not needed for example cut out, so
// this class is neither complete nor correct
template<typename T>
class clone_ptr
{
public:
clone_ptr() : ptr(nullptr) {}
operator bool() { return ptr!=nullptr; }
T* operator->() { return ptr; }
private:
clone_ptr(T* p) : ptr(p) {}
T* ptr;
template<class T1,class U1, typename ...Args>
friend clone_ptr<T1> make_cloned( Args ...args );
};
template<typename T, typename U=T, …
Run Code Online (Sandbox Code Playgroud) 我有以下代码,在gcc和clang上表现得如预期的那样.但是,MSVC给了我一个意想不到的结果.
让我们先看看有问题的代码.
#include <iostream>
// -----------------------------------------------
class Test // Dummy for MCVE
{
public:
Test();
void Print();
private:
int arr[5];
};
Test tst;
// -----------------------------------------------
template<typename T>
struct range // some stuff not needed by example removed
{
constexpr range(T n) : b(0), e(n) {}
constexpr range(T b, T e) : b(b), e(e) {}
struct iterator
{
T operator*() { return i; }
iterator& operator++() { ++i; return *this; }
bool operator!=(iterator other) { return i != other.i ; } …
Run Code Online (Sandbox Code Playgroud) 我正在为容器编写一个drop-replacement,我正在努力获得所有异常保证.我正在编写该clear
方法,我希望它尽可能地完成,并始终将容器保持在一致状态,即使其中一个析构函数抛出异常.我也想在清洁完毕后重新抛出异常,最好不要切片.
这让我想到了这个问题; 什么时候被破坏了?让我们看一下尝试:这个例子简化了.
void container::clear()
{
bool had_exception = false;
std::exception* exp;
internal_set_empty(); // this cant throw
while( ! internal_done() )
{
try
{
internal_destruct_next(); // this might throw if T::~T() throws
}
catch( std::exception& e )
{
had_exception = true;
exp = &e;
}
}
if( had_exception )
throw *exp;
}
Run Code Online (Sandbox Code Playgroud)
我希望这会严重失败,因为异常可能在被认为是被处理时被破坏,这在技术上不会重新抛出.
另一个尝试是获取异常的副本,我期望切片.
有没有办法延长异常的生命周期,以便稍后重新抛出它?如果可能的话,我也希望能够重新抛出通过的异常catch(...)
.
标准中有关隐式移动的措辞在 c++23 中发生了变化,
请参阅https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2266r3.html
相关部分是:
返回的符合移动条件的 id 表达式始终是 xvalue
这似乎打破了流行但不明智的“不动”
template<typename T>
auto unmove(T&& v) -> std::remove_reference_t<T>& { return v; }
Run Code Online (Sandbox Code Playgroud)
当前的实现似乎同意:https ://godbolt.org/z/3n39rGM7b
这个重大改变是有意为之的,还是我们可以期待灾难恢复?