为什么/何时应该在std :: vector <>上使用std :: unique / shared_ptr(std :: vector <>)?

时间:2019-03-07 21:33:05

标签: c++ c++11

当我可以简单地使用std::unique/shared_ptr(std::vector<>)时,我对std::vector<>的主要用法有些困惑,据我所知,@Configuration @EnableTransactionManagement @EnableSwagger2 @EnableJpaRepositories(basePackages = "com.restfulproject.crud.repositories") @ComponentScan(basePackages = "com.restfulproject.crud.*") public class WebConfig extends WebMvcConfigurationSupport{ @Bean public Docket userApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .apiInfo(metaData()); } @Primary @Bean public SwaggerResourcesProvider swaggerResourcesProvider(InMemorySwaggerResourcesProvider defaultResourcesProvider) { return () -> { SwaggerResource wsResource = new SwaggerResource(); wsResource.setName("swagger"); wsResource.setSwaggerVersion("2.0"); wsResource.setLocation("/api/config/swagger.json"); List<SwaggerResource> resources = new ArrayList<>(defaultResourcesProvider.get()); resources.add(wsResource); return resources; }; } @Bean WebMvcConfigurer configurer () { return new WebMvcConfigurerAdapter() { @Override public void addResourceHandlers (ResourceHandlerRegistry registry) { registry.addResourceHandler("/api/config/swagger.json"). addResourceLocations("classpath:/config/swagger.json"); } }; } @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addRedirectViewController("/api/v2/api-docs", "/v2/api-docs"); registry.addRedirectViewController("/api/swagger-resources/configuration/ui", "/swagger-resources/configuration/ui"); registry.addRedirectViewController("/api/swagger-resources/configuration/security", "/swagger-resources/configuration/security"); registry.addRedirectViewController("/api/swagger-resources", "/swagger-resources"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/api/swagger-ui.html**").addResourceLocations("classpath:/META-INF/resources/swagger-ui.html"); registry.addResourceHandler("/api/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); } private ApiInfo metaData() { return new ApiInfoBuilder() .title("User Crud REST API") .description("\"Projeto que utiliza spring boot\"") .version("1.0.0") .license("Apache License Version 2.0") .licenseUrl("https://www.apache.org/licenses/LICENSE-2.0\"") .build(); } } 本身就是一个动态数组。正如我在周围所看到的,人们说这两者之间没有任何性能差异。因此,基于所有这些,使用指向容器(在本例中为向量)而不是向量的智能指针有什么意义?

1 个答案:

答案 0 :(得分:2)

首先,除非您需要与std::shared_ptr相关的特定“共享所有权”语义,否则不应该使用std::shared_ptr。如果需要智能指针,则默认情况下应默认为std::unique_ptr,并且仅在明确需要时才离开它。

第二:表面上,相比std::unique_ptr<TYPE>,更喜欢TYPE的原因是如果您计划将对象移动很多。这是不可移动或移动昂贵的大型对象的通用设计范例。他们实现了一个Copy构造函数,而没有实现Move构造函数,因此移动被迫表现得像Copy。

但是,

std::vector确实具有相对有效的移动语义:如果移动std::vector,无论其包含的类型有多复杂,该移动仅构成几个指针交换。移动std::vector并不会招致大量的计算复杂性,这没有真正的风险。即使在您覆盖先前分配的数组(调用向量中所有对象的析构函数)的情况下,如果您使用std::unique_ptr<std::vector<TYPE>>来代替,那么您仍然会遇到这种复杂性,什么都不做。

std::unique_ptr<std::vector<TYPE>>有两个优点。第一个是它摆脱了隐式副本构造函数。也许您想强制维护程序员不要复制该对象。但这是相当利基的用途。另一个优点是,它允许您规定没有向量的情况,即vec.size() == 0doesNotExist(vec)的条件不同。但是即使在那种情况下,您也应该更喜欢std::optional<std::vector>,它可以更好地通过代码传达对象的意图。当然,std::optional仅在C ++ 17→代码中可用,因此也许您处于尚未实现它的环境中。但是否则,没有理由使用std::unique_ptr<std::vector>

因此,总的来说,我不认为std::unique_ptr<std::vector>有实际用途。它和std::vector之间没有实际的性能差异,使用它只会使您的代码变得不必要地复杂。