通过按位运算确定返回类型(Determining return type via bitwise operation)
我在java文档中游荡,突然发现这段代码:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
谁能解释一下返回声明后会发生什么样的魔法? 好的,该方法的结果由lambda表达式与功能界面结合确定。 但那之前写的是什么? 它是通过按位运算转换返回类型吗? 我不明白。 据我所知,bitwise仅适用于数字。 我在哪里可以更具体地阅读这个案例?
I was wandering throught java docs and suddenly found this code:
public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2)); }
Can anyone explain what kind of magic is going on after the return statement? Okay, the result of the method is determined by lambda expression in combination with functional interface. But what is it written before that? Is it casting return type via bitwise operation? I don't get it. As far I know bitwise is applicable only with numbers. Where can I read about this case more specifically?
原文:https://stackoverflow.com/questions/30061674
最满意答案
你的析构函数肯定是错的。 类的析构函数不会也不能
delete
该对象的内存。如果没有虚函数,你对公共继承的反对意见是什么? (至少)有两种方法可以防止某人通过基指针意外删除派生对象。 一个是
protected
基础析构函数。另一种方法是将派生类的动态分配实例直接填充到
shared_ptr
。 这甚至可以是shared_ptr<Base>
:std::shared_ptr<Base> foo(new DerivedA(...));
由于
shared_ptr
具有捕获其参数类型的模板构造函数,因此Base*
指针将在与shared_ptr
关联的删除函数中转换为DerivedA*
,因此会被正确删除。 没有人会如此愚蠢地尝试从shared_ptr
提取指针并将其删除为Base*
。当然,如果你没有虚函数,那么当衍生类之间的唯一区别就是它们在构造函数中设置的时候,这个技巧才真正有用。 否则,您最终需要从
shared_ptr
向下转换Base*
指针,在这种情况下,您应该首先使用shared_ptr<DerivedA>
。Your destructor is definitely wrong. The destructor of a class does not and must not
delete
the memory for the object.What's your objection to public inheritance without virtual functions? There are (at least) a couple of ways to prevent someone accidentally deleting a derived object through a base pointer. One is to make the base destructor
protected
.Another is to stuff dynamically-allocated instances of the derived class straight into a
shared_ptr
. This can even be ashared_ptr<Base>
:std::shared_ptr<Base> foo(new DerivedA(...));
Because
shared_ptr
has a template constructor that captures the type of its argument, theBase*
pointer will be converted toDerivedA*
in the deleter function associated with theshared_ptr
, and hence deleted correctly. Nobody should ever be so daft as to try to extract a pointer out of ashared_ptr
and delete it asBase*
.Of course if you have no virtual functions, then the trick is only really useful when the only difference between the derived classes is what they set up in their constructors. Otherwise you'll end up needing to downcast the
Base*
pointer from theshared_ptr
, in which case you should have used ashared_ptr<DerivedA>
to begin with.
相关问答
更多-
C ++析构函数返回(C++ destructor with return)[2022-03-26]
不,你不能通过return语句来防止对象被破坏,这只是意味着在这个时候,dtor的身体的执行就会结束。 之后,还会被毁坏(包括其成员和基地),记忆仍将被释放。 你迁移异常。 Class2::~Class2() noexcept(false) { if (status != FINISHED) throw some_exception(); } Class1::~Class1() { myClass2->status = FINISHED; try { delete ... -
C ++:CRTP析构函数?(C++ : CRTP destructor?)[2021-09-29]
你的析构函数肯定是错的。 类的析构函数不会也不能delete该对象的内存。 如果没有虚函数,你对公共继承的反对意见是什么? (至少)有两种方法可以防止某人通过基指针意外删除派生对象。 一个是protected基础析构函数。 另一种方法是将派生类的动态分配实例直接填充到shared_ptr 。 这甚至可以是shared_ptr: std::shared_ptr foo(new DerivedA(...)); 由于shared_ptr具有捕获其参数类型的模板构造函数,因此Base*指 ... -
是的,析构函数是完全冗余的。 如你所说,代码中还有其他警告标志。 例如,使用typedef struct在C ++中没有任何意义,它与空的析构函数一样多余:代码是由C ++编写的边际掌握,一定会有更多的错误(一方面,类名无效)由于全球范围的领先优势)。 Yes, the destructor is completely redundant. As you’ve said yourself the code has other warnings signs. Using typedef struct for ...
-
CRTP(C ++)的各种错误(Various errors with CRTP (C++))[2022-01-17]
你需要实现你的专业功能: template<> const string& Entity::name() const { return _name; } template<> Client& Entity ::name(const string& name) { _name = name; return *This(); } 并且还添加公共继承: class Client : public Entity 所以你可以访问name() ... -
C ++析构函数示例(C++ destructor example)[2023-05-28]
对于ListElement,使值为0,链接为0(NULL)。 您不需要重置析构函数中的任何值,因为在执行析构函数后,值不会存在。 您需要确定的主要事情是使用delete堆上分配的所有元素(即使用new )(或者在数组的情况下delete [] )。 对于LinkedList,遍历元素并为所有元素调用ListElementDestructor。 对于在堆栈上分配的对象,当对象超出范围时,将自动调用该对象。 对于动态分配的对象(即使用new创建),在使用delete析构函数时会调用析构函数。 换句话说,如果正确 ... -
C ++需要析构函数(C++ need for destructor function)[2022-02-14]
这是成员自己不负责的额外清理。 或者在资源管理的情况下确保与他对象相关的资源被正确释放。 请记住并非所有成员都会调用析构函数(指针没有析构函数)。 所以如果你有指针,你需要手动管理它们。 带指针的示例资源管理。 shared_ptr::~shared_ptr() { if (decrementReferenceCountAndCheckForZero()) { cleanupResources(); } } 例。 使用框架。 没有一个成员知道框架,但工作人员知道。 ... -
C ++中的析构函数(destructor in C++)[2022-08-24]
您遇到错误和无关的警告。 这个错误是因为你为析构函数使用了一个初始化器,这是没有意义的,也不是有效的语法。 你要: ~AB() { } // destructor 警告是因为你没有声明你的析构函数是虚拟的。 具有虚拟方法的类应该具有虚拟析构函数 : virtual ~AB() { } You're getting an error and an unrelated warning. The error is because you're using an initializer for your des ... -
出于同样的原因,你在C#中有一个Dispose方法和一个Finalizer。 粗略地说,在C ++ / CLI中,析构函数对应于Dispose,Finalilzer对应于终结器。 我粗略地说,因为C ++ / CLI为您实现了Dispose模式 。 也就是说,如果调用delete(即调用析构函数),它将确保终结器被抑制。 如果未调用delete,则终结器将在GC时运行。 就像在C#中一样 在析构函数中,您可以清理托管对象和非托管对象。 在终结器中,您只能清理非托管对象,因为此时(当垃圾收集器正在运行时),此 ...
-
如果要显式调用析构函数,则必须从与被调用的析构函数相同类型的对象中调用它。 否则,这将产生未定义的行为: 在显式析构函数调用中,析构函数名称显示为〜后跟类型名称或decltypespecifier,表示析构函数的类类型。 析构函数的调用遵循成员函数的通常规则(9.3); 也就是说,如果对象不是析构函数的类类型而不是从析构函数的类类型派生的类(包括通过空指针值调用析构函数),则程序具有未定义的行为。 另请注意,如果显式调用析构函数,则在实例所在的作用域的末尾,只要对象已在堆栈上实例化,析构函数将被隐式第二次调 ...
-
C ++ CRTP类层次结构(C++ CRTP class hierarchy)[2022-08-27]
使用CRTP支持更深层次的继承层次结构通常是通过在继承层次结构中在您自己的类之间“插入”CRTP类来实现的: struct empty {}; templatestruct crtp_services : Base {}; class base : public crtp_services {}; class derived : public crtp_services {}; cl ...