我正在使用void*在某些功能中接受的 API 。我经常不小心将错误的指针类型传递给函数,当然它编译得很好,但在运行时不起作用。
有没有办法禁用void*指向某个类的指针的隐式转换?
如果我有这样的嵌套类:
class MyClass
{
class NestedClass
{
public:
// nested class members AND definitions here
};
// main class members here
};
Run Code Online (Sandbox Code Playgroud)
目前,定义MyClass是在CPP文件中,但定义NestedClass是在头文件中,也就是说,我不能在CPP文件中声明函数/构造函数.
所以我的问题是,如何定义NestedClasscpp文件中的函数?如果我不能,那是什么原因(如果是这种情况,我对于为什么会发生这种情况有一个模糊的想法,但我想要一个很好的解释)?结构怎么样?
[这是一个受到其他地方最近讨论的启发的问题,我会用它来提供答案.]
我想知道数组"衰减"指针的奇怪C现象,例如当用作函数参数时.这似乎是不安全的.用它明确地传递长度也是不方便的.我可以通过其他类型的聚合 - 结构 - 完全符合价值; 结构不会腐烂.
这个设计决定背后的理由是什么?它如何与语言集成?为什么结构有区别?
C++20 标准在Function Call 7.6.1.3/8 中说:
参数的初始化(包括每个关联的值计算和副作用)相对于任何其他参数的初始化是不确定的。
不确定排序(与未排序相反)可确保影响同一内存区域的副作用不是未定义的行为。Cppreference给出了以下示例:
f(i = -2, i = -2); // C++17 之前未定义的行为 f(++i, ++i); // C++17 之前未定义的行为, C++17 之后未指定
C++17 中的变化似乎并未出现在引用的部分中,尽管其措辞在几个世纪以来基本上保持不变。(好的;在 n3337 中这只是一个注释。)
一个简单的示例会引发来自 gcc 和clang的警告:
void f(int fa, int fb);
void m() // contains code calling f()
{
int a = 11;
f(++a, ++a);
cout << "after f(): a=" << a << '\n';
}
Run Code Online (Sandbox Code Playgroud)
<source>:6:7: warning: multiple unsequenced modifications to 'a' [-Wunsequenced]
f(++a, ++a); …Run Code Online (Sandbox Code Playgroud) 我有一个file.txt包含内容的文件
i love this world
I hate stupid managers
I love linux
I have MS
Run Code Online (Sandbox Code Playgroud)
当我执行以下操作时:
for line in `cat file.txt`; do
echo $line
done
Run Code Online (Sandbox Code Playgroud)
它给出了类似的输出
I
love
this
world
I
..
..
Run Code Online (Sandbox Code Playgroud)
但我需要输出如下面的整行 - 任何想法?
i love this world
I hate stupid managers
I love linux
I have MS
Run Code Online (Sandbox Code Playgroud) 我不是问"为什么这个计算结果是NaN",我问"为什么NaN存在,而不是导致异常或错误?"
我一直想知道这一点,并与人们一起讨论.
我得到的唯一答案就是"你不想尝试 - 抓住每一个分歧,你呢?" 或"有些情况下NaN是有效的结果".
话虽如此,我从来没有收到过NaN作为有效结果的具体例子.假设NaN不可能是一个有效的结果,我不明白为什么它存在.如果它出现,据我所知,你有一个错误.期.
您希望程序崩溃并在那里死亡,以便您可以轻松找到出错的地方.这不是让程序运行失败,而是可能写入损坏的数据,可能发送损坏的数据,或做各种令人讨厌的事情 - 在不可避免地崩溃之前.(如"实用程序员"中所述 - 崩溃,不要垃圾")
现在,我相信IEEE 754的设计师比我聪明得多,这让我相信它是其存在的理由.这是什么原因?
这个问题源于 Eric Postpischil在另一个帖子中的评论。
我很难理解可变长度数组(VLA)作为函数参数的使用:
sizeof()下面的调用所示;即使完全有可能在堆栈上传递整个数组,就像定义 VLA 时在堆栈上创建一样。那么,如果 VLA 参数没有提供任何优势并且像指针的任何其他数组参数一样进行调整,那么为什么该语言允许使用 VLA 参数声明函数呢?如果语言不使用大小表达式(例如检查实际参数的大小)并且在函数内部无法获得大小表达式(仍然必须为此传递一个显式变量),为什么要对大小表达式进行求值?
为了更清楚地说明我感到困惑的地方,请考虑以下程序(此处为实时示例)。所有函数声明显然都是等效的。但正如 Eric 在另一个线程中指出的那样,函数声明中的参数大小表达式是在运行时评估的评估的。大小表达式不会被忽略。
我不清楚这会带来什么好处,因为大小及其评估没有影响(除了可能的副作用)。特别是,重复一遍,该信息不能被函数内部的代码使用。最明显的变化是在类似堆栈的结构上传递 VLA。毕竟,它们通常也在调用方的堆栈上。但与恒定长度的数组一样,类型在声明时已调整为指针 - 下面的所有声明都是等效的。尽管如此,仍会评估无用且被丢弃的数组大小表达式。
#include <stdio.h>
// Nothing to see here.
extern void ptr(int *arr);
// Identical to the above.
extern void ptr(int arr[]);
// Still identical. Is 1 evaluated? Who knows ;-).
extern void ptr(int arr[1]);
// Is printf evaluated when called? Yes.
// But the array is still …Run Code Online (Sandbox Code Playgroud) 考虑以下程序:
#include<iostream>
using namespace std;
struct S
{
S() = default;
S(const S& other) = delete;
S(S&& other) = delete;
int i;
};
S nakedBrace()
{
return {}; // no S constructed here?
}
S typedBrace()
{
return S{};
}
int main()
{
// produce an observable effect.
cout << nakedBrace().i << endl; // ok
cout << typedBrace().i << endl; // error: deleted move ctor
}
Run Code Online (Sandbox Code Playgroud)
示例会话:
$ g++ -Wall -std=c++14 -o no-copy-ctor no-copy-ctor.cpp
no-copy-ctor.cpp: In function 'S typedBrace()':
no-copy-ctor.cpp:19:12: …Run Code Online (Sandbox Code Playgroud) 我正在使用 MS Visual Studio 2017, V. 15.9.8。
我正在使用优秀的 JetBrains ReSharper Ultimate 2019.1.2 Build 191.0.20190603.142841。它在指定的位置给我一个警告:
#include <vector>
struct T
{
std::vector<char> m;
const char *f() const
{
static const char emptyData; // ReSharper complains here
return m.size() ? &m[0] : &emptyData;
}
};
Run Code Online (Sandbox Code Playgroud)
消息是
file.h:应该初始化类型为“const unsigned char”的静态局部变量。这是非标准的 Microsoft C++ 扩展。
如果emptyData不是 const ,警告就会消失。
警告是错误的,因为所有静态数据,包括常量静态局部变量,都是按照标准的零初始化,对吧?
我正在尝试从字符串中以十六进制表示法读取字节。字节可能会或可能不会被空格分隔,例如,这" 00 ffab c "是一个有效的例子,应该导致读取 4 个字节,0x00、0xff、0xab 和 0x0c。问题是跳过空格但只读取两个相邻的数字(如果存在)。
如果输入是来自一个文件,任务将是一样容易while(fscanf(f, "%2d", &i) == 1) ...,因为sscanf空白,读出位置由基础跟踪跳跃FILE,和宽度仅应用到物品的最大场读,不包含空白原始输入字符。但是从字符串中读取时无法进行位置跟踪;我需要使用%n格式转换说明符,它将到目前为止通过此调用读取的字符数存储到关联变量中,例如scanf(f, "%2d%n", &i, &readIncr),并通过添加相应的增量手动维护读取位置。
这有点麻烦,因此我想使用std::istringstreamwhich来跟踪底层字符串中的位置。
但是在输入流上设置宽度并没有预期的(和预期的)效果;下面是一个最小的演示;为简单起见,我使用十进制整数。输入字段宽度的文档和示例很少。
难道我做错了什么?我这个用例根本不是故意的?
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
using namespace std;
int main()
{
const char *s = " 1234";
int i;
istringstream is(s);
if (is >> setw(2) >> i)
{
cout << "stringstream i: " << i << '\n';
} …Run Code Online (Sandbox Code Playgroud)