【问题标题】:Using an object by calling class constructor explicitly vs by default initialization + assignment operator通过显式调用类构造函数与默认初始化+赋值运算符来使用对象
【发布时间】:2016-12-02 03:56:55
【问题描述】:

考虑以下示例:

#include <wx/bitmap.h>

int main()
{
    wxBMPHandler h;

    wxImage::AddHandler(&h);

    wxBitmap bm = wxBitmap(200, 200);
    bm.SaveFile("file.bmp", wxBITMAP_TYPE_BMP);

    return 0;
}

由于我只使用h 来调用AddHandler() 而不是其他任何事情,我想避免完全定义它,而是在一行中完成整个事情。所以我想把它替换为:

wxImage::AddHandler(&wxBMPHandler());

编译得很好,但是调用SaveFile() 将不起作用; WxWidgets 将在运行时显示“没有定义类型 1 的图像处理程序”的错误。

我猜在函数调用中创建的对象是临时的,但我不确定。如果没有,我错过了什么,如何避免定义h

值得注意的是,AddHandler() 具有以下签名:

static void AddHandler( wxImageHandler *handler );



[更新] 回应M.M的评论说:

wxImage::AddHandler(&wxBMPHandler());应该无法编译,除非 该类为右值重载了 operator&

由于在 WxWidgets 的源代码中找不到 operator& 的定义,我创建了这个测试项目:

#include <iostream>
#include <string>

using namespace std;

string* address = nullptr;

void testing(string* input)
{
    *input = "Something else entirely";
    address = input;
}

int main()
{
    testing(&string("Life is a test"));

    cout << *address << endl;

    cin.get();
    return 0;
}

它编译得很好,并且运行时没有任何“硬错误”——唯一需要注意的是屏幕上没有显示任何内容——(*address).empty() 返回 true。 我什至定义了我自己的类来测试,而不是 std::string 并产生了相同的行为(没有编译器错误,没有运行时错误,但没有输出)。

按照aichao 的建议,我也尝试了这种单线,但没有成功:

wxImage::AddHandler(shared_ptr<wxBMPHandler>(new wxBMPHandler()).get());

【问题讨论】:

  • 要使其成为一行,您需要在堆上创建它并使其成为shared_ptr。否则,临时变量会超出范围。
  • wxImage::AddHandler(&amp;wxBMPHandler()); 应该无法编译,除非该类为右值重载了 operator&amp;
  • @aichao 你能具体说明一下吗?我试过wxImage::AddHandler(shared_ptr&lt;wxBMPHandler&gt;(new wxBMPHandler()).get()); - 效果不佳。
  • @M.M 嗯,我不确定。请参阅我对问题正文的更新。
  • 您必须查阅 MSVC 文档以了解 &amp;wxBMPHandler() 的行为

标签: c++ function pointers wxwidgets


【解决方案1】:

我以前从未使用过wxWidgets,但根据wxWidgets version 3.1.1 API docs here,您应该使用堆分配的处理程序对象调用wxImage::AddHandler

wxImage::AddHandler(new wxBMPHandler);

因此,无需定义h。同样根据文档,此处理程序对象的内存由wxWidgets 框架管理。具体来说,文档说handler 是一个

堆分配的处理程序对象将被wxImage 删除,如果它稍后被RemoveHandler() 删除或在程序关闭时删除。

还有静态成员函数wxImage::CleanUpHandlers() 用于删除所有已注册的图像处理程序。根据文档:

这个函数在退出时被 wxWidgets 调用。

因此,您不必自己删除处理程序,除非您特别想要(即释放一些内存)。

希望这会有所帮助。

【讨论】:

  • @Marc.2377 事实上,当调用wxImage::CleanUpHandlers() 时,您在使用原始代码退出程序时没有遇到问题,这让我很惊讶。请参阅此SO question/answer 了解原因。你用的是哪个编译器?
  • 这太好了,谢谢。我正在使用 MSVC 2015 Update 3 btw 进行测试;使用最高警告级别并启用 SDL 检查。
【解决方案2】:

wxImage::AddHandler(&amp;wxBMPHandler());中,临时停止的生命周期在表达式的末尾,所以你有悬空指针。

wxBMPHandler h;

wxImage::AddHandler(&h);

wxBitmap bm = wxBitmap(200, 200);
bm.SaveFile("file.bmp", wxBITMAP_TYPE_BMP);

h 比调用 bm.SaveFile("file.bmp", wxBITMAP_TYPE_BMP); 的寿命更长。

你会遇到类似的问题

{
    wxBMPHandler h;

    wxImage::AddHandler(&h);
} // End of life time of h

wxBitmap bm = wxBitmap(200, 200);
bm.SaveFile("file.bmp", wxBITMAP_TYPE_BMP);

【讨论】:

    猜你喜欢
    • 2013-03-16
    • 1970-01-01
    • 2012-01-02
    • 2021-11-26
    • 1970-01-01
    • 2011-04-17
    • 1970-01-01
    • 1970-01-01
    • 2019-11-16
    相关资源
    最近更新 更多