标签: implicit-conversion

如何修复隐式转换警告?

我正在阅读《C++ 如何编程》第 9 版,尝试学习 C++,并尝试使用第 7 章中的骑士问题进行练习。

根据输出中的“64”,代码显然存在某种逻辑错误(我将自行修复),但在执行此操作之前,我一直致力于理解以及如何处理编译器警告。

我已将 board 声明为 unsigned int 的二维数组,因为它只能包含值 0-7。同样,出于同样的原因,我将 for 循环中的变量声明为 unsigned int。

我在 stackoverflow 上读过有关此问题的回复,但它们很快就超出了我的理解范围。

#include <iostream>
#include <array>
#include <iomanip>

using namespace std;

void printArray(const array< array< unsigned int, 8 >, 8 >);

int main() {
  array< array< unsigned int, 8 >, 8 > board = {};
  array< int, 8 > horizontal = {{ 2, 1, -1, -2, -2, -1, 1, 2 }};
  array< int, 8 > vertical = {{ -1, -2, …
Run Code Online (Sandbox Code Playgroud)

c++ unsigned signed implicit-conversion c++11

2
推荐指数
1
解决办法
8045
查看次数

强制 C++ 更喜欢带有隐式转换的重载而不是模板

我有一种情况,我需要重载解析来更喜欢带有隐式转换的重载而不是同名的模板函数。

考虑以下示例:

#include <iostream>
#include <functional>

void call_function(const std::function<void()>& function)
{
   std::cout << "CALL FUNCTION 1" << std::endl;
   function();
}

template <typename Function>
void call_function(const Function& function)
{
    std::cout << "CALL FUNCTION 2" << std::endl;
    function();
}

int main()
{
    // Pass a lambda to "call_function"
    // This lambda is implicitly convertible to 'std::function<void()>'
    // Even though it is implicitly convertible, the template function is selected by the compiler.
    call_function([]{
        std::cout << "TEST" << std::endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

输出:

CALL FUNCTION …
Run Code Online (Sandbox Code Playgroud)

c++ templates overload-resolution implicit-conversion c++11

2
推荐指数
2
解决办法
97
查看次数

为什么编译器在 printf 中将 char 转换为 int?

我正在使用https://cppinsights.io/。以下是代码(默认示例)

#include <cstdio>

int main()
{
    const char arr[10]{2,4,6,8};
    for(const char& c : arr)
    {
      printf("c=%c\n", c);
    }
}
Run Code Online (Sandbox Code Playgroud)

关于cppinsights

C++ Insights 是一个基于 clang 的工具,可以进行源到源的转换。它的目标是让事情可见,这通常是有意地在幕后发生。这是关于编译器为我们做的事情的魔法。或者查看编译器的类。

这是生成的代码,这是编译器如何看待代码

#include <cstdio>

int main()
{
  const char arr[10] = {2, 4, 6, 8, '\0', '\0', '\0', '\0', '\0', '\0'};
  {
    char const (&__range1)[10] = arr;
    const char * __begin1 = __range1;
    const char * __end1 = __range1 + 10L;
    for(; __begin1 != __end1; ++__begin1) {
      const char & c = *__begin1;
      printf("c=%c\n", …
Run Code Online (Sandbox Code Playgroud)

c++ implicit-conversion

2
推荐指数
1
解决办法
74
查看次数

具有 C11 标准的编译器接受的替代函数指针语法

我不确定这个函数指针类型声明语法,但它有效。语法就像声明一个普通的旧函数。

typedef struct Element GetChildCallback(void *userdata, usize parent, usize child_no);
Run Code Online (Sandbox Code Playgroud)

我找不到任何关于它是否符合标准或它可能有哪些缺点的信息。

我认为这仅适用于 typedef,所以我更进一步,发现这也适用于常规函数参数:

extern inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...));

inline void dmpstrn(const char *t, usize n, int printer(const char *fmt, ...)) {
    usize len = strlen(t) > n ? n : strlen(t);
    printer("\"");
    for (usize i = 0; i < len; i += 1) {
        if (t[i] == '\n') 
            printer("\\n");
        else
            printer("%c", t[i]);
    }
    printer("\"\n");
}

// ...

int main() {
    dmpstrn("Hello\nworld", UINT64_MAX, …
Run Code Online (Sandbox Code Playgroud)

c typedef function-pointers implicit-conversion function-declaration

2
推荐指数
1
解决办法
76
查看次数

为什么我会出现无限循环?简单的问题,简短的代码

如果输入数组为空,则array.size()应该为 0。第一个for,从0array.size() - 1,应该意味着它从0-1,对吗?

for那么,不应输入此值,并且该函数应返回 inversionsCounter 值,该值将是0

但这并没有发生,代码进入了无限循环。为什么是这样?

这是代码:

#include <vector>
#include <iostream>

using namespace std;

int countInversions(vector<int> array)
{    
    int inversionsCounter = 0;
    for (int i = 0; i < array.size() - 1; ++i)
        for (int j = i + 1; j < array.size(); ++j)
            if (array[i] > array[j])
                ++inversionsCounter;

    return inversionsCounter;
}

int main()
{
    vector<int> array = {};
    cout << array.size();
    cout << …
Run Code Online (Sandbox Code Playgroud)

c++ for-loop vector infinite-loop implicit-conversion

2
推荐指数
1
解决办法
221
查看次数

临时初始化和参考初始化

我想了解如何引用初始化。例如,我们看一个典型的例子。

double val = 4.55;
const int &ref = val;
Run Code Online (Sandbox Code Playgroud)

我可以想到上面代码片段中发生的事情的两种可能性。

可能性1

通常的解释如下:

这里创建了一个带有值类型的临时(纯右值),然后将引用绑定到这个临时(纯右值)对象,而不是直接绑定到变量。发生这种情况是因为右侧变量的类型是,而左侧我们有一个引用。但是为了将引用绑定到变量,类型应该匹配。此外,临时纯右值的生命周期也得到了延长。int4refintvalvaldoubleint

可能性2

我认为还有另一种可能发生的情况,如下:

这里创建了一个具有值类型的临时(纯右值)。但由于需要一个左值并且当前我们有一个纯右值,因此临时物化开始,因此纯右值被转换为xvalue。然后引用绑定到这个具体化的 xvalue(因为 xvalue 也是泛左值) ,而不是直接绑定到变量。发生这种情况是因为右侧变量的类型是,而左侧我们有一个引用。但是为了将引用绑定到变量,类型应该匹配。此外,物化临时 xvalue 的生命周期也延长了。int4const int &refrefvalvaldoubleint

我的问题是:

  1. 根据C++11标准,以上解释哪一个是正确的。我愿意接受上述解释都不正确,在这种情况下,正确的解释是什么。
  2. 根据C++17标准,以上解释哪一个是正确的。我愿意接受上述解释都不正确,在这种情况下,正确的解释是什么。
  3. 我也很困惑上述两种可能性的第一步中的纯右值是否实际上是一个临时对象?或者 xvalue 是实际对象。我的意思是我们是否有 2 个临时对象,例如第一个由于“纯右值转换”而导致的第二个临时对象由于“纯右值到 xvalue”转换(临时物质化)而导致。或者我们是否只有一个临时值,这是由于“prvalue to xvalue”临时物化所致。

PS:我并不是在寻找解决这个问题的方法。例如,我知道我可以简单地写: const double …

c++ language-lawyer implicit-conversion c++11 c++17

2
推荐指数
1
解决办法
284
查看次数

了解涉及浮点类型的除法后的舍入结果

在 Postgres 14 中,我看到的舍入结果对我来说没有意义。试图了解发生了什么事。在所有情况下,我都会将19除以3

将任一integer值转换为real

SELECT  19::real /3;
Run Code Online (Sandbox Code Playgroud)

产生的值为6.333333333333333

SELECT 19/3::real;
Run Code Online (Sandbox Code Playgroud)

产生的值为6.333333333333333

然而,将双方都转换为real产量:

SELECT 19::real/3::real;  
Run Code Online (Sandbox Code Playgroud)

产生的值为6.3333335

有趣的是,如果我将两边都转换为double precisionor float,答案是6.333333333333333

SELECT 19.0 / 3.0;
Run Code Online (Sandbox Code Playgroud)

产量6.333333333333333

SELECT 19.0::real / 3.0::real;
Run Code Online (Sandbox Code Playgroud)

产量6.3333335

SELECT ( 16.0 / 3.0) :: real;
Run Code Online (Sandbox Code Playgroud)

产量6.3333335

我现在看到:

SELECT 6.333333333333333::real;
Run Code Online (Sandbox Code Playgroud)

产量6.33333335

所以真正的问题似乎是:

  1. 为什么我们以这种奇怪的方式四舍五入(我知道实数/浮点数是不精确的,但这似乎很极端。)

  2. 数据类型是什么19::real / 3;

postgresql floating-point rounding type-conversion implicit-conversion

2
推荐指数
1
解决办法
170
查看次数

为什么 `function&lt;void (string)&gt;` 和 `function&lt;string (string)&gt;` 参数类型有时对于重载来说不明确?

跟进我的问题c++ - 使用中间类型时隐式转换如何工作?,从中我了解了1 隐式转换 max的规则,我试图了解涉及函数参数的更高级用例。

假设我有一个函数,它接受另一个函数作为参数。该函数参数可以返回某些内容,也可以不返回任何内容(void)。因此,我想重载函数定义,在一种情况下接受非 void 函数参数,在另一种情况下接受 void 函数参数。

using VoidType = void (string);
using NonVoidType = string (string);

string call(VoidType *fn, string arg) {
    cout << "[using void function]" << endl;
    fn(arg);
    return arg;
}

string call(NonVoidType *fn, string arg) {
    cout << "[using non void function]" << endl;
    return fn(arg);
}
Run Code Online (Sandbox Code Playgroud)

调用函数时,给定参数具有已知类型,因此重载选择应该很简单,如下所示:

void printVoid(string message) {
    cout << message << endl;
}

string printNonVoid(string message) {
    cout << message << endl;
    return message;
} …
Run Code Online (Sandbox Code Playgroud)

c++ overloading ambiguous implicit-conversion std-function

2
推荐指数
1
解决办法
402
查看次数

通过引用传递 2d 向量

我读了很多关于这个主题的回复,但我仍然无法理解。请理解我正在学习过程中。

有人告诉我,向量只不过是它的第一个元素地址,因此是一个二维向量。

那么,为什么如果我通过指针传递 2D 向量,我就会失去使用索引的能力。

int vec[10][10] = { 1, 2, 3, 4 };
int *v = vec;
Run Code Online (Sandbox Code Playgroud)

为什么我不能说

int a = v[1][1]  
Run Code Online (Sandbox Code Playgroud)

就像我会做的那样

int a = vec[1][1] 
Run Code Online (Sandbox Code Playgroud)

if v,那是一个指向int, 的指针,而vec, 那是一个指向int, 的指针,那么它们不是完全相同的东西,同一个对象吗?

我读到

int (*v)[N] = vec;
Run Code Online (Sandbox Code Playgroud)

其中N是列数。但这对于初学者来说似乎是一件超级棘手的事情。

为什么是这样?

编辑

我的大脑想到了这个解释,int (*vec)[N]解释了指向向量 10 的指针的int含义。这里是。

鉴于我的理解,在二维数组中,指向第一个元素的指针是指向N元素数组的指针,这是我给自己的解释。

如果 lhs ofint *var = &int必须从右到左读取,变成“ varis a pointerto int”,那么我期望int [N] …

c pointers multidimensional-array implicit-conversion

2
推荐指数
1
解决办法
149
查看次数

从int**到const int的转换无效**

我有一个类,其中一个二维数组的int实现为int**.我按如下方式为这个2D数组实现了一个访问器函数,返回一个const int**以防止用户编辑它:

const int** Class::Access() const
{
     return pp_array;
}
Run Code Online (Sandbox Code Playgroud)

但是我得到了编译错误"从int**到const int**的无效转换".为什么不允许在这里推广const?如何在不编辑权限的情况下授予用户访问信息的权限?

c++ const multiple-indirection implicit-conversion

1
推荐指数
1
解决办法
1985
查看次数