什么时候以及为什么要使用String&,String和Const?

如何解决什么时候以及为什么要使用String&,String和Const?

我正在编写一段代码。

struct Argument
        {
                Argument(): s_name(""),name(""),optional(true) {}
                Argument(String& s_name_inp,String& name_inp,bool optional_inp):s_name(s_name_inp),name(name_inp),optional(optional_inp){}
        .....More code.....
        }

稍后在代码中的某个地方

void addArgument(String& name_inp,bool optional=true)
    {
            String name;
            //Creating a tmep string to store the corrected name if the user doesn't enter - or -- wrt. name of their argument.
            name = isDashed(name_inp) ? name_inp : addDash(name_inp) ;
            //using the dashed name to check if it's shortname or long name.

            if(name.size()>3)
            {
                    //This is the long name.
                    Argument arg("",name,optional);
                    insertArgument(arg);
            }
            else
            {
                    //This is for the short name
                    Argument arg(name,"",optional);
                    insertArgument(arg);
            }
    }

Struct Argument和fn addArgument都是类的一部分,其中struct Argument在private中定义,而addArgument在公共中定义。

运行代码时抛出错误。 对于长名-

error: no instance of constructor "ArgumentParser::Argument::Argument" matches the argument list 
            argument types are: (const char [1],ArgumentParser::String,__nv_bool)

一个简称--

error: no instance of constructor "ArgumentParser::Argument::Argument" matches the argument list
            argument types are: (ArgumentParser::String,const char [1],__nv_bool)

我可以弄清楚如何解决它。由于输入了空字符串"",因此出现此错误。在struct Argument构造函数中添加const可以解决此问题。

struct Argument
        {
                Argument(): s_name(""),optional(true) {}
                Argument(const String& s_name_inp,const String& name_inp,optional(optional_inp){}
        .....More code.....
        }

类似地,声明一个String blank = "" ;并在初始化struct Argument而不是""的obj时传递它也可以解决该问题。另外,在Argument构造函数中传递String而不是String&也可以解决问题-

Argument(String s_name_inp,String name_inp,optional(optional_inp){}

因此,我由此得出的结论是,仅传递""是一个问题,因为它没有存储在某些变量中。它没有某些可以引用的位置(字符串和),以防代码内部发生更改。这就是为什么在构造函数的String&之前添加一个const可以确保即使我们通过ref传递,编译器也不会进行任何更改,因此编译器允许使用""

但是,即使我没有执行任何不正确的操作,我也不明白为什么编译器如此“智能”。就像编译器也在弹出“安全性”漏洞一样,除了我们经常犯的“错误”。


关于这个问题,我也想从更广泛的意义上理解const的使用。

我明白这只是为了确保不会更改要传递(或返回)给函数/构造函数的变量。但是,如果我作为程序员可以确保我不会更改变量,为什么我们需要它。那么为什么我们需要const?

我知道的一件事是,它可以用来告诉其他人,如果他们看到您的代码,则保持参数不变。(https://www.youtube.com/watch?v=4fJBrditnJU是学习const的良好来源)而且,使用之间有什么区别这两种情况下const中的-

int somefunc const(int& var)
{
 //   var=4; This isn't allowed due to the const in fn
    return var;
}

int somefunc(const int& var)
{
// var =4 ; This is also not allowed.
    return var;
}

此外,我想知道如果引用引用和值传递仅用于赋值,即它们没有进行任何更改,而是用于检查条件或对它们进行某些赋值,则它们之间有何不同?其他变种。

添加const String&就像保证,无论用户传递的是什么,在代码中都不会被篡改,因此我们不能简单地用String替换它吗?因为按值传递将实例化传递的变量/参数的副本?为什么我们使用const String&then?


关于传递指针和通过引用传递的另一个问题:我知道的String&(或int&或任何其他)的唯一用途是直接将实际的“事物”传递给函数,而不是其副本,因此无论我们做什么该“事物”将反映在原始事物上,就像我们使用指针来获取对实际“事物”所做的更改一样,而不是对其进行复制。为什么我们不使用指针而不是通过引用传递?它带来什么好处?

我知道这个问题有点大,但这些都是相互关联的问题。回答一个就称赞另一个。感谢任何花时间回答他们认为合适的人!

解决方法

在大多数情况下,指针和l值引用可以互换。只需在调用位置编写即可。

正如您所注意到的,const &&之间的区别来自一个简单的引用,该引用需要变量进行引用。带有&的引用的语义是“让我为您写下来”。 const &允许即时创建临时副本,其语义为“让我看看”。价值传递的含义是“给我一份副本,我决定如何处理”。

根据实际经验,避免复印是您的首要考虑。因此,对于大于整数值的值,您应该避免按值调用。

常量正确性主要只是C ++语言的设计,从技术角度来看并不是严格要求的。您可以认为它是一种表达“相信我,我不会破坏它”的方式。

关于将临时值传递给简单的&参数,请先仔细考虑一下谁真正拥有该临时值,以及将存在多长时间。如果允许您写入任何内容,将会丢失。

还要考虑默认参数,例如void foo(const bar &foobar = bar(42))。绝对不允许将它们作为非const引用,因为这会导致未定义的行为。该默认对象可能存在于静态范围内(而不是每个调用者都重新创建它),并且有人弄乱了它会导致更改默认值。祝您找到该错误的根源。

即使对于非默认参数,const &允许在编译时创建临时变量(constexpr构造函数),也可以将相同临时对象的多个实例折叠到内存中的单个实例中。没有const的保证,这种优化同样是不可能的。

还有很多其他情况,其中const-正确性也是启用编译器优化的关键。因此,即使您认为自己的代码纪律至少会阻止未定义的行为,通常也要正确使用它。

,

但是,如果我作为程序员可以确保我不会更改变量,为什么我们需要它。那么为什么我们需要const?

您还可以确保在编码中不犯任何错误,因此为什么要进行编译器错误/警告,单元测试,问题跟踪器……

添加const String&就像保证,无论用户传递的是什么,在代码中都不会被篡改,因此我们不能简单地用String替换它吗?因为按值传递将实例化传递的变量/参数的副本?为什么我们使用const String&then?

  • 与引用上的间接引用相比,复制一个类可能会更昂贵。尤其是如果在const &情况下编译器能够内联函数的情况下,根本不会发生任何间接作用。
  • 副本可能会带来不良的副作用(在资源有限的环境中可能会出现问题)
  • 一个类可能有一个删除的副本构造函数,因此根本不可能复制,但是您仍然要确保const正确性。

我对String&(或int&或其他任何字符)的唯一了解是直接将实际的“事物”传递给函数,而不是函数的副本,因此我们对“事物”所做的任何操作都将反映在原始,就像我们使用指针来获取要对实际“事物”进行的更改一样,而不是对其进行复制。为什么我们不使用指针而不是通过引用传递?它带来什么好处?

指针可以接受nullptr,因此您需要处理传递nullptr的情况(如果不必传递nullptr,则可以使用gsl::not_null)。但是使用指针不允许传递临时变量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-