【问题标题】:expected primary-expression before ‘...’, c++ compile error'...'之前的预期主表达式,c ++编译错误
【发布时间】:2021-05-29 23:17:31
【问题描述】:

在 SO 上有很多类似标题的帖子,但它们似乎是由各种语法错误触发的,我还没有看到一致的模式..

using namespace std;

class A
{
public:
    A(int a_) : a(a_) {}
    int a;
};

int main()
{
    A x{3};
    A y{0};

    if ((y=x).a)
        cout << y.a << endl;
        
    int i = 1;
    if (int j = i)
        cout << j << endl;
    
    if ((A z = x).a) // error: expected primary-expression before ‘z’
        cout << z.a << endl;

    (int m = 1); // error: expected primary-expression before ‘int’
}

假设A z = x 是一个赋值表达式,它应该与z 具有相同的值,我错了吗?

【问题讨论】:

标签: c++ syntax compiler-errors


【解决方案1】:

我认为A z = x 是一个赋值表达式是不是错了

是的,你错了。这里没有任务。此语句中的= 表示初始化,而不是赋值。语句A z = x; 定义了变量z,其中z 是从x 构造的。这里使用的是复制构造函数,而不是复制赋值。这是declaration statement,不是表达式语句。

您的困惑相当普遍,而且由于if 语句中的条件可以是带有大括号或等号初始化程序的单个非数组变量的声明,这一事实变得更糟。从语法上讲,带有“等于”初始化器的声明看起来很像赋值。正如您所发现的,一个很大的区别是您不能将声明视为子表达式。条件是要么声明表达式,不是两者的混合

好消息是 C++-17 在 if 语句语法中添加了一个可选的 init-statement。因此,您似乎想要的可以通过以下方式实现。

    if ( A z = x; z.a )  // Semicolon separates init-statement from condition
        cout << z.a << endl;
    // At the end of the `if` statement, `z` goes out of scope.

【讨论】:

    【解决方案2】:

    您不能以这种方式在if 语句中声明变量。声明必须采用以下形式:

    if (X x = y) ...(或if (auto x = y) ...

    但是,如果您在 A 类中提供合适的转换运算符,您仍然可以实现您想要做的事情,如下所示:

    #include <iostream>
    
    using namespace std;
    
    class A
    {
    public:
        A(int a_) : a(a_) {}
        int a;
        operator bool () { return a != 0; }
    };
    
    int main()
    {
        A x{3};
        const A &y = x;
        if (y.a)
            cout << y.a << endl;
        if (A z = x)
            cout << z.a << endl;
    }
    

    Live demo

    【讨论】:

    • 谢谢!实际上Astd::map.a.size(),我不想从map 派生,只是为.size() 添加bool ()。我想解决方法是定义一个临时变量?喜欢auto &amp; val = func(); if (val.size()) blahblah;
    • 是的,我会这样做。是从std::map派生出来的UB。
    • UB?派生标准库类没有UB。
    • @StoryTeller-UnslanderMonica 好的,我的立场是正确的。但我认为至少它是气馁的。
    • 当多态删除必须发生时很糟糕,因为它不能。但这就是它的范围,它与任何课程都是一样的。标准容器的大多数用途根本不涉及这一点。主要使用值语义和通过引用传递。
    猜你喜欢
    • 2011-03-31
    • 1970-01-01
    • 2021-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 2023-04-11
    相关资源
    最近更新 更多