我在C#中遇到了这个新功能,它允许在满足特定条件时执行catch处理程序.
int i = 0;
try
{
throw new ArgumentNullException(nameof(i));
}
catch (ArgumentNullException e)
when (i == 1)
{
Console.WriteLine("Caught Argument Null Exception");
}
Run Code Online (Sandbox Code Playgroud)
我想知道什么时候这可能有用.
一种情况可能是这样的:
try
{
DatabaseUpdate()
}
catch (SQLException e)
when (driver == "MySQL")
{
//MySQL specific error handling and wrapping up the exception
}
catch (SQLException e)
when (driver == "Oracle")
{
//Oracle specific error handling and wrapping up of exception
}
..
Run Code Online (Sandbox Code Playgroud)
但这又是我可以在同一个处理程序中执行的操作,并根据驱动程序的类型委托给不同的方法.这是否使代码更容易理解?可以说没有.
我能想到的另一个场景是:
try
{
SomeOperation();
}
catch(SomeException e)
when (Condition == true)
{ …Run Code Online (Sandbox Code Playgroud) 我不确定这是编译器的问题还是我做错了.我正在使用Visual Studio 2013编译器.
我有一个类,我需要在构造函数初始化列表中获取大量资源,其中大部分都可以抛出异常.我在函数try块中包装了成员初始化列表,并在那里捕获了异常.但是我的程序仍然会中止,即使catch子句没有重新抛出异常.我不允许发布实际代码.所以我用这个等效的演示代码重现了这个问题.有人可以帮我解决这个问题吗?
#include <iostream>
using namespace std;
class A{
public:
A() try : i{ 0 }{ throw 5; }
catch (...){ cout << "Exception" << endl; }
private:
int i;
};
int main(){
A obj;
}
Run Code Online (Sandbox Code Playgroud)
在执行此代码时,我得到一个Windows警报"abort()已被调用".所以我猜系统将此视为未捕获的异常并调用terminate().
另一方面,如果我在try(catch)块中的main()中包装对象的构造,则正确捕获异常并且程序正常终止.
有人可以告诉我,如果我在这里做错了吗?
我试图理解为什么std::function无法区分重载函数.
#include <functional>
void add(int,int){}
class A {};
void add (A, A){}
int main(){
std::function <void(int, int)> func = add;
}
Run Code Online (Sandbox Code Playgroud)
在上面显示的代码中,function<void(int, int)>只能匹配其中一个功能,但它会失败.为什么会这样?我知道我可以通过使用lambda或函数指针到实际函数然后将函数指针存储在函数中来解决这个问题.但为什么这会失败?关于我想要选择哪个功能的上下文不清楚吗?请帮助我理解为什么这会失败,因为我无法理解为什么在这种情况下模板匹配失败.
我得到的编译错误如下:
test.cpp:10:33: error: no viable conversion from '<overloaded function type>' to
'std::function<void (int, int)>'
std::function <void(int, int)> func = add;
^ ~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1266:31: note:
candidate constructor not viable: no overload of 'add' matching
'std::__1::nullptr_t' for 1st argument
_LIBCPP_INLINE_VISIBILITY function(nullptr_t) : __f_(0) {}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__functional_03:1267:5: note:
candidate constructor not viable: no overload of 'add' …Run Code Online (Sandbox Code Playgroud) 时隔很长一段时间,我又回到了 C#,并试图使用《C# 10 in a Nutshell》一书来跟上进度。
\n作者在那里提到,将属性的访问器从 更改为init或set反之亦然是一个重大更改。我可以理解如何将其更改为set可能init是一个重大更改,但我只是无法理解为什么以其他方式更改它会是一个重大更改。
例如:
\n// Assembly 1\nTest obj = new(){A = 20};\n\n// Assembly 2\nclass Test\n{\n public int A {get; init;} = 10;\n}\nRun Code Online (Sandbox Code Playgroud)\n即使我将init属性访问器更改为.Assembly 1 中的此代码也不应受到影响set。那么为什么这是一个重大变化呢?
我正在阅读Stanley Lippman的书C++ Primer,以了解有关C++ 11的更多信息.
在关于通用算法的章节中,他提到泛型算法中使用的迭代器可以根据它们支持的操作分为5种类型:输入迭代器,输出迭代器,前向迭代器,双向迭代器和随机访问迭代器.
从他的书中引用:
输入迭代器可以读取序列中的元素.它们必须提供以下运算符 - equality(
==),inequality(!=),dereference(*),postfix&prefix increment(++)和箭头operator(->).输入迭代器只能按顺序使用.我们保证*it++有效,但增加输入迭代器可能会使该流上的所有其他迭代器无效.因此,无法保证我们可以保存输入迭代器的状态并通过保存的迭代器检查元素
我无法用粗体理解这句话.为什么递增一个仅用于读取元素的输入迭代器会使其他迭代器无效?为什么我们不能保存输入迭代器的状态?
我刚开始学习C++ 11中的新功能.我正在阅读C++ Primer(Stanley Lippman)中的lambdas并正在尝试它们.
我尝试了以下代码:
auto func() -> int (*) (){
//int c=0;
return []()-> int {return 0;};
}
int main(){
auto p = func();
}
Run Code Online (Sandbox Code Playgroud)
这段代码编译得很好.所以我猜没有任何捕获的lambdas只是由编译器生成为普通函数,我们可以使用它们的普通函数指针.
现在我更改了代码以使用捕获:
auto func() -> int (*) (){
int c=0;
return [=]()-> int {return c;};
}
int main(){
auto p = func();
}
Run Code Online (Sandbox Code Playgroud)
但这无法编译.使用g ++时出现以下编译错误:
main.cpp: In function ‘int (* func())()’:
main.cpp:6:31: error: cannot convert ‘func()::__lambda0’ to ‘int (*)()’ in return
return [=]()-> int {return c;};
Run Code Online (Sandbox Code Playgroud)
从错误中我可以理解,它不是生成的普通函数,它可能是一个带有重载调用操作符的类.或者是别的什么?
我的问题:编译器如何在内部处理lambdas?我应该如何传递使用捕获的lambda,即func()的返回值应该是什么?我目前无法想到一个用例,我需要使用这样的lambdas,但我只是想了解更多关于它们的信息.请帮忙.
谢谢.
我试图了解 memory_order_relaxed 的细节。我指的是这个链接:CPP 参考。
#include <future>
#include <atomic>
std::atomic<int*> ptr {nullptr};
void fun1(){
ptr.store(new int{0}, std::memory_order_relaxed);
}
void fun2(){
while(!ptr.load(std::memory_order_relaxed));
}
int main(){
std::async(std::launch::async, fun1);
std::async(std::launch::async, fun2);
}
Run Code Online (Sandbox Code Playgroud)
问题1:在上面的代码中,即使设置ptr的线程已经完成运行,fun2在技术上是否可能处于无限循环中,它看到ptr的值为nullptr?
如果假设,我将上面的代码更改为如下所示:
#include <future>
#include <atomic>
std::atomic<int> i {0};
std::atomic<int*> ptr {nullptr};
void fun1(){
i.store(1, std::memory_order_relaxed);
i.store(2, std::memory_order_relaxed);
ptr.store(new int{0}, std::memory_order_release);
}
void fun2(){
while(!ptr.load(std::memory_order_acquire));
int x = i.load(std::memory_order_relaxed);
}
int main(){
std::async(std::launch::async, fun1);
std::async(std::launch::async, fun2);
}
Run Code Online (Sandbox Code Playgroud)
相关问题:在上面的代码中,fun2 是否有可能将原子 i 的值视为 1 或者是否可以保证它会看到值 2?
我试图了解约束(类或泛型方法)如何影响方法本身。以这段代码为例:
class Base<T> where T:class, IComparable<T>
{
public virtual void Method(T obj) { }
}
class Derived<T> : Base<T> where T:class, IComparable<T>, IEnumerable<T>
{
public override void Method(T obj) { }
}
Run Code Online (Sandbox Code Playgroud)
此代码编译良好,并且编译器/运行时能够解析对非泛型方法“Method”的多态调用,该方法采用泛型类型的参数。在基类和派生类中,对类型参数的约束是不同的。
我还指定了一个类约束来排除值类型,这可能会导致问题,因为为每个值类型实例化生成一个不同的类,而对于引用类型只实例化一个这样的类。
另一方面,以下代码无法编译。
class Base
{
public virtual void Method<T>() where T : class, IComparable<T> { }
}
class Derived : Base
{
public override void Method<T>() where T : class, IComparable<T>, IEnumerable<T> { }
}
Run Code Online (Sandbox Code Playgroud)
C# 的语言规范规定,对泛型方法的约束会像对重写方法一样被继承,并且指定任何这样的约束是非法的。我在 Google 上进行了一些搜索,发现这是不允许的,因为与支持多态调用相关的复杂性(相对于维护方法表等)。但我仍然不明白为什么它在上面的情况 1 中工作,它与此类似,只是它是泛型类。编译器/运行时如何能够在情况 1 中执行此操作,而情况 2 被标记为编译器错误?
我试图在Essential C#6.0(MarkMichaelis和EricLippert)的方法调用过程中理解装箱/拆箱的影响,最终比我开始时更加困惑.
这是本书的代码:
struct A
{
public int Val {get; set;};
//doesn't override ToString
}
A vo = new A();;
object thing;
// Boxing
thing = vo;
string text = ((A)thing).ToString();
Console.WriteLine(text);
Run Code Online (Sandbox Code Playgroud)
作者继续说以下内容:
如果接收器是未装箱的并且结构不覆盖ToString(),则必须调用基类实现,并且它期望引用对象作为其接收器.因此,接收器是盒装的.
在上面的代码中就是这种情况,其中A的强制转换操作符将取消装入'thing'然后尝试在临时上调用ToString.由于ToString()方法尚未在结构A中被重写,因此只有在强制转换(A)生成的临时框或者编译器完全优化取消装箱/装箱后,才会调用ToString.
但是生成的CIL如下所示,确实表明"事物"已经被取消装箱,但是对ToString()的调用发生时却没有被重新装箱.请帮我理解这个.
.locals init (valuetype Chapter7.A V_0,
object V_1,
string V_2,
valuetype Chapter7.A V_3)
IL_0000: nop
IL_0001: ldloca.s V_0
IL_0003: initobj Chapter7.A
IL_0009: ldloc.0
**IL_000a: box Chapter7.A** //thing = vo
IL_000f: stloc.1
IL_0010: ldloc.1
**IL_0011: unbox.any Chapter7.A** //((A)thing)
IL_0016: stloc.3
IL_0017: ldloca.s V_3 //the temporary where …Run Code Online (Sandbox Code Playgroud) C++ 标准说,原子上的 RMW(读-修改-写)操作将对原子变量的最新值进行操作。因此memory_order_relaxed,当从多个线程并发执行时,使用这些操作不会影响 RMW 操作。
我假设只有当 RMW 操作存在一些内存屏障或栅栏时,即使指定的内存顺序是“放松的”,这种行为也是可能的。如果我的理解有误,请纠正我,并解释如果不使用此类内存屏障,这些操作如何处理最新值。如果我的理解是正确的,那么我是否可以进一步假设使用 Acquire-Release 或 Seq-CST 内存顺序不应该对 RMW 操作产生额外的性能影响,比如 ARM 或 Alpha 等弱排序架构。提前致谢。
我对继承层次结构中的Move构造函数有疑问。在C ++ Primer(Stanley Lippman)中,提到了继承层次结构中的move构造函数将定义如下:
class Base { /* Default Copy control and move constructor */ };
class D : public Base {
public:
D(const D& d) : Base(d) {/*initializers for members of D */} //This is ok
D(D&& d): Base(std::move(d)) {/*initializers for members of D */}
};
Run Code Online (Sandbox Code Playgroud)
在move构造函数中,我尝试在调用基本move构造函数时删除std :: move,因为'd'是一个右值引用。
D(D&& d): Base(d) {/*initializers for members of D */}
Run Code Online (Sandbox Code Playgroud)
但这最终调用了基类副本构造函数,而不是move构造函数。
为了理解为什么需要std :: move,我在这个论坛上进行了搜索以查看以前的讨论,并且发现了一些答复,这些答复说尽管d是右值引用,但在派生类的move构造函数中它仍然是左值。因此,我们需要在其上调用std :: move,以确保调用了基类move构造函数。我了解这部分。
但是从C ++ Primer中,我了解到一旦调用了std :: move,我们之后就不应再使用该对象。在调用std :: move的表达式结束后,对象将保持有效状态以进行销毁,但其所保存的值可能没有意义。
因此,当我们调用std :: move委托给基类的move构造函数时,当我们回到派生类的move构造函数的主体时,对象将如何保持有意义的状态。
换一种说法:
D(D&& d): Base(std::move(d)) { …Run Code Online (Sandbox Code Playgroud) 我正在尝试为另一个类定义一个枚举。
这是我的代码
import lombok.AllArgsConstructor;
@AllArgsConstructor
public enum State {
PUBLISHED("published"),
UNPUBLISHED("unpublished");
private String value;
public String value() {
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
但我不断收到此错误:
[错误] .../State.java:[12,14] 枚举 State 中的构造函数 State 不能应用于给定类型;[错误] 必需:没有参数 [错误] 找到:java.lang.String [错误] 原因:实际参数列表和正式参数列表的长度不同
@AllArgsConstructor有什么问题吗?
我试图在C++ Concurrency in Action(第2版)中修改Anthony William的代码并遇到一些错误.详情如下:
这是Anthony Williams的原始代码:
template<typename Func>
std::experimental::future<decltype(std::declval<Func>()())> spawn_async(Func&& func){
std::experimental::promise<decltype(std::declval<Func>()())> p;
auto res=p.get_future();
std::thread t(
[p=std::move(p),f=std::decay_t<Func>(func)]() mutable{
try{
p.set_value_at_thread_exit(f());
} catch(...){
p.set_exception_at_thread_exit(std::current_exception());
}
});
t.detach();
return res;
}
Run Code Online (Sandbox Code Playgroud)
我想修改上面的代码,以便spawn_async接受任何可调用而不是仅具有空参数列表的调用.
这是我的代码:
spawn_async.hpp
#include <future>
#include <thread>
#include <functional>
#include <type_traits>
template<typename Func, typename... Args>
auto spawn_async(Func&& func, Args&&... args)
{
std::promise<std::result_of_t<Func(Args&&...)>> prom;
auto res = prom.get_future();
auto lambda = [p = std::move(prom), f=std::decay_t<Func>(func)](auto&&... a) mutable
{
try
{
p.set_value_at_thread_exit(f(a...));
}
catch (...)
{
p.set_exception_at_thread_exit(std::current_exception());
}
};
auto async_func …Run Code Online (Sandbox Code Playgroud) c++ ×8
c++11 ×5
c# ×4
abi ×1
c++14 ×1
enums ×1
generics ×1
java ×1
lambda ×1
lombok ×1
memory-model ×1
properties ×1
std-function ×1
stdatomic ×1
templates ×1