首页 \ 问答 \ 通过按位运算确定返回类型(Determining return type via bitwise operation)

通过按位运算确定返回类型(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
更新时间:2023-08-03 18:08

最满意答案

你的析构函数肯定是错的。 类的析构函数不会也不能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 a shared_ptr<Base>:

std::shared_ptr<Base> foo(new DerivedA(...));

Because shared_ptr has a template constructor that captures the type of its argument, the Base* pointer will be converted to DerivedA* in the deleter function associated with the shared_ptr, and hence deleted correctly. Nobody should ever be so daft as to try to extract a pointer out of a shared_ptr and delete it as Base*.

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 the shared_ptr, in which case you should have used a shared_ptr<DerivedA> to begin with.

相关问答

更多
  • 不,你不能通过return语句来防止对象被破坏,这只是意味着在这个时候,dtor的身体的执行就会结束。 之后,还会被毁坏(包括其成员和基地),记忆仍将被释放。 你迁移异常。 Class2::~Class2() noexcept(false) { if (status != FINISHED) throw some_exception(); } Class1::~Class1() { myClass2->status = FINISHED; try { delete ...
  • 你的析构函数肯定是错的。 类的析构函数不会也不能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 ...
  • 你需要实现你的专业功能: template<> const string& Entity::name() const { return _name; } template<> Client& Entity::name(const string& name) { _name = name; return *This(); } 并且还添加公共继承: class Client : public Entity 所以你可以访问name() ...
  • 对于ListElement,使值为0,链接为0(NULL)。 您不需要重置析构函数中的任何值,因为在执行析构函数后,值不会存在。 您需要确定的主要事情是使用delete堆上分配的所有元素(即使用new )(或者在数组的情况下delete [] )。 对于LinkedList,遍历元素并为所有元素调用ListElementDestructor。 对于在堆栈上分配的对象,当对象超出范围时,将自动调用该对象。 对于动态分配的对象(即使用new创建),在使用delete析构函数时会调用析构函数。 换句话说,如果正确 ...
  • 这是成员自己不负责的额外清理。 或者在资源管理的情况下确保与他对象相关的资源被正确释放。 请记住并非所有成员都会调用析构函数(指针没有析构函数)。 所以如果你有指针,你需要手动管理它们。 带指针的示例资源管理。 shared_ptr::~shared_ptr() { if (decrementReferenceCountAndCheckForZero()) { cleanupResources(); } } 例。 使用框架。 没有一个成员知道框架,但工作人员知道。 ...
  • 您遇到错误和无关的警告。 这个错误是因为你为析构函数使用了一个初始化器,这是没有意义的,也不是有效的语法。 你要: ~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); 也就是说,如果对象不是析构函数的类类型而不是从析构函数的类类型派生的类(包括通过空指针值调用析构函数),则程序具有未定义的行为。 另请注意,如果显式调用析构函数,则在实例所在的作用域的末尾,只要对象已在堆栈上实例化,析构函数将被隐式第二次调 ...
  • 使用CRTP支持更深层次的继承层次结构通常是通过在继承层次结构中在您自己的类之间“插入”CRTP类来实现的: struct empty {}; template struct crtp_services : Base {}; class base : public crtp_services {}; class derived : public crtp_services {}; cl ...

相关文章

更多

最新问答

更多
  • 如何检索Ember.js模型的所有属性(How to retrieve all properties of an Ember.js model)
  • maven中snapshot快照库和release发布库的区别和作用
  • arraylist中的搜索元素(Search element in arraylist)
  • 从mysli_fetch_array中获取选定的值并输出(Get selected value from mysli_fetch_array and output)
  • Windows Phone上的可用共享扩展(Available Share Extensions on Windows Phone)
  • 如何在命令提示符下将日期设置为文件名(How to set file name as date in command prompt)
  • 如何在Laravel 5.2中使用paginate与关系?(How to use paginate with relationships in Laravel 5.2?)
  • 从iframe访问父页面的id元素(accessing id element of parent page from iframe)
  • linux的常用命令干什么用的
  • Feign Client + Eureka POST请求正文(Feign Client + Eureka POST request body)
  • 怎么删除禁用RHEL/CentOS 7上不需要的服务
  • 为什么Gradle运行测试两次?(Why does Gradle run tests twice?)
  • 由于有四个新控制器,Auth刀片是否有任何变化?(Are there any changes in Auth blades due to four new controllers?)
  • 如何交换返回集中的行?(How to swap rows in a return set?)
  • 在android中的活动之间切换?(Switching between activities in android?)
  • Perforce:如何从Depot到Workspace丢失文件?(Perforce: how to get missing file from Depot to Workspace?)
  • Webform页面避免运行服务器(Webform page avoiding runat server)
  • 在ios 7中的UITableView部分周围绘制边界线(draw borderline around UITableView section in ios 7)
  • 内存布局破解(memory layout hack)
  • 使用Boost.Spirit Qi和Lex时的空白队长(Whitespace skipper when using Boost.Spirit Qi and Lex)
  • 我们可以有一个调度程序,你可以异步添加东西,但会同步按顺序执行吗?(Can we have a dispatcher that you can add things todo asynchronously but will be executed in that order synchronously?)
  • “FROM a,b”和“FROM a FULL OUTER JOIN b”之间有什么区别?(What is the difference between “FROM a, b” and “FROM a FULL OUTER JOIN b”?)
  • Java中的不可变类(Immutable class in Java)
  • bat批处理文件结果导出到txt
  • WordPress发布查询(WordPress post query)
  • 如何在关系数据库中存储与IPv6兼容的地址(How to store IPv6-compatible address in a relational database)
  • 是否可以检查对象值的条件并返回密钥?(Is it possible to check the condition of a value of an object and JUST return the key?)
  • 德州新起点计算机培训学校主要课程有什么?
  • GEP分段错误LLVM C ++ API(GEP segmentation fault LLVM C++ API)
  • “latin1_german1_ci”整理来自哪里?(Where is “latin1_german1_ci” collation coming from?)