我想有一个简单的方法来检查对象是否有效.我想到了一个简单的转换函数,如下所示:
operator bool() const { return is_valid; }
Run Code Online (Sandbox Code Playgroud)
检查它是否有效现在非常简单
// is my object invalid?
if (!my_object) std::cerr << "my_object isn't valid" << std::endl;
Run Code Online (Sandbox Code Playgroud)
这被认为是一种好习惯吗?
我很想知道它是如何nullptr工作的。标准 N4659 和 N4849 说:
std::nullptr_t;sizeof(std::nullptr_t) == sizeof(void*);bool为false;(void*)0,但不能向后转换;所以它基本上是一个与 具有相同含义的常量(void*)0,但它具有不同的类型。我std::nullptr_t在我的设备上找到了实现,如下所示。
#ifdef _LIBCPP_HAS_NO_NULLPTR
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS nullptr_t
{
void* __lx;
struct __nat {int __for_bool_;};
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
operator _Tp* () const {return 0;}
template <class _Tp, class …Run Code Online (Sandbox Code Playgroud) 以下是否会出现编译错误?
delete cout;
delete cin;
Run Code Online (Sandbox Code Playgroud)
答案是不.
它是标准库中流类实现的一个缺陷.它们具有以下要转换的转换函数void*,这意味着,所有流对象都可以隐式转换为void*:
operator void * ( ) const;
Run Code Online (Sandbox Code Playgroud)
这一般非常有用,因为它可以让我们在从文件读取输入时编写非常惯用的循环.但与此同时,它让用户可以写delete stream.正如我所说,您可以删除任何流对象.所以这些都是允许的:
delete ss; //declare std::stringstream ss;
delete iss; //declare std::istringstream iss;
delete oss; //declare std::ostringstream oss;
Run Code Online (Sandbox Code Playgroud)
只有他们会发出警告,说(见ideone):
警告:删除'void*'未定义
你可以轻易地通过铸造来避免,比如说char*.但该程序仍然存在问题,并且在运行时很可能会崩溃.
-
所以我的问题是,在C++ 11中这个问题已得到解决和修复吗?以下文章提供了此问题的一个修复:
-
编辑:
来自@ Xeo对@ Alf答案的评论:
提出修复此问题的论文:
为什么一个能投射出std::ostream的void指针?我不知道有任何这样的转换运算符std::ostream.代码如下
#include <iostream>
int main()
{
void *p = std::cout; // why does this work?
}
Run Code Online (Sandbox Code Playgroud)
我问这个问题,因为我已经看到new调用了一个放置操作符
Foo* pFoo = new (std::cerr) Foo;
Run Code Online (Sandbox Code Playgroud)
并且完全不知道为什么会写这样的东西.
PS:我正在使用或不使用g ++ 4.9.2进行编译-std=c++11.clang ++ 不接受代码.
PSS:发现由于所谓的"安全bool问题"(参见@ nicebyte的回答),在预C++ 11 void*中定义了一个转换运算符std::ostream,然后在C++ 11中将其删除.但是,我的代码使用g ++在C++ 11中编译得很好.更重要的是,clang ++拒绝它,无论我使用什么版本的标准,即使有-std=c++98,尽管我的理解是它应该接受,如果编译为pre-C++ 11.
operator void*() constC++流类中有一个转换函数.这样所有流对象都可以隐式转换为void*.在与SO的程序员交互过程中,他们建议我不要使用,void*除非你有充分的理由使用它.void*是一种删除类型安全和错误检查的技术.因此,由于该转换功能的存在,以下程序完全有效.这是C++标准库中的一个缺陷.
#include <iostream>
int main()
{
delete std::cout;
delete std::cin;
}
Run Code Online (Sandbox Code Playgroud)
上述程序在C++ 03中有效,但在C++ 11及更高版本的编译器中编译失败,因为此转换函数已被删除.但问题是,如果它是危险的,它是C++标准库的一部分?允许将流对象转换为的目的是void*什么?有什么用?
c++ void-pointers c++-standard-library delete-operator c++11
我一直在阅读代码,QScopedPointer并发现了一些我无法理解的东西.
这是QScopedPointercode.qt.io 上的相关代码:
template <typename T, typename Cleanup = QScopedPointerDeleter<T> >
class QScopedPointer
{
typedef T *QScopedPointer:: *RestrictedBool;
public:
...
#if defined(Q_QDOC)
inline operator bool() const
{
return isNull() ? Q_NULLPTR : &QScopedPointer::d;
}
#else
inline operator RestrictedBool() const
{
return isNull() ? Q_NULLPTR : &QScopedPointer::d;
}
#endif
...
inline bool isNull() const
{
return !d;
}
...
protected:
T *d;
Run Code Online (Sandbox Code Playgroud)
我理解使QDoc认为QScopedPointer具有的预处理器定义operator bool而不是operator RestrictedBool.我不明白它的用途RestrictedBool是什么以及它是如何做到的.例如,更简单的实现是:
inline operator bool() const …Run Code Online (Sandbox Code Playgroud) 在这个答案中,我谈到使用std::ifstream对象的转换bool来测试流是否仍处于良好状态.我查看了Josuttis的书以获取更多信息(如果你感兴趣,请查看600页),事实证明这些iostream物体实际上已超载operator void*.当流不好(可以隐式转换为false)时返回空指针,否则返回非空指针(隐式转换为true).他们为什么不过载operator bool?
我遇到了一个我无法自己回答的问题.此外,我没有在谷歌和这里找到答案.比如,我想在if子句中"检查对象的有效性",如下所示:
MyClass myObject;
// [some code, if any]
if (!myObject)
{
// [do something]
}
Run Code Online (Sandbox Code Playgroud)
我们MyClass这样定义:
class MyClass
{
public:
MyClass() { };
virtual ~MyClass() { };
bool operator!()
{
return !myBool;
};
operator bool()
{
return myBool;
};
private:
bool myBool = 0;
};
Run Code Online (Sandbox Code Playgroud)
我现在的问题是:在这个if子句中实际使用了哪一个重载运算符?无论哪种方式,结果显然都是一样的.
什么是最先进的大约功能检查值是否设置与否?
例如,下面的迭代器解析单元格.一些单元格包含值,其他单元格为空.
什么是最方便的方式?
struct iterator
{ //usage:
bool isset() const // if (it.isset())
bool isSet() const // if (it.isSet())
bool empty() const // if (it.empty())
bool is_set() const // if (it.is_set())
bool is_valid() const // if (it.is_valid())
operator void*() const; // if (it)
explicit operator bool() const; // if ((bool)it) or if(it) //thanks @stijn
operator bool() const; // if (it) //why not implicit conversion?
bool operator!() const; // if (!!it)
//throwing exception as pointed out by …Run Code Online (Sandbox Code Playgroud) 此示例使用整数,运算符和另一个整数读取行.例如,
// sstream-line-input.cpp - Example of input string stream.
// This accepts only lines with an int, a char, and an int.
// Fred Swartz 11 Aug 2003
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
//================================================================ main
int main() {
string s; // Where to store each line.
int a, b; // Somewhere to put the ints.
char op; // Where to save the char (an operator)
istringstream instream; // Declare an input string stream
while …Run Code Online (Sandbox Code Playgroud)